繁体   English   中英

为了清楚起见,我想在 Dart 中使用命名参数。 我应该如何处理它们?

[英]I want to use named parameters in Dart for clarity. How should I handle them?

TL;DR:作为有意识的设计选择的结果,命名参数是可选的。 缺乏官方语言支持,有没有办法强制(和通知)所需的命名参数?


我发现在定义类时使用命名参数非常有用。 以 MMORPG 中的一项Ability为例:

class Ability {

  final name;
  final effectDuration;
  final recast;            // wait time until next use
  // ...
}

effectDurationrecast两个携带相同类型的信息(即,持续时间),并用相同的数据类型有可能表示。 很容易混淆哪个数字去哪里。 但是,它们都是对对象正确性至关重要的信息,因此在实例化过程中不能丢失它们。

我可以通过 try-catch 来破坏程序以强制执行这些参数的要求,但这对于使用该类并且不知道的人来说听起来并不有趣(缺乏阅读文档并直观地理解该类的作用) ) 他们是必需的。

有什么方法可以强制执行某些命名参数的要求,同时设法将所述要求通知给调用者和/或帮助他们正确使用它?

meta包提供了@required支持的@required注释。

Flutter @required使用它并直接从import 'package:flutter/foundation.dart'提供@required

foo({@required String name}) {...}

foo(); // results in static warning

@required不检查传递的值是否为null ,只检查实际在调用站点上传递的值。 要检查null您还可以使用assert()来检查传递的值

class Ability {
  Ability(this.name, this.effectDuration, this.recast) : assert(name != null), assert(effectDuration != null), assert(recast != null);
  final name;
  final effectDuration;
  final recast;            // wait time until next use
  // ...
}    

[更新] Dart 2.0 的新版本

在 dart 2.0 中, required关键字已作为空安全更新的一部分添加到语言中。 这意味着您会得到一个编译器强制的非空值,而不是由分析器检查的值; 这使得空检查完全多余。

这意味着,该代码有效地做同样的旧代码的下方,除非你永远不会有关于断言投掷的值担心nameeffectDuration ,而recast不能为空。

class Ability {
  final String name;
  final Duration effectDuration;
  final bool recast;
  final String? description;

  Ability({
    required this.name,
    this.effectDuration = Duration(seconds: 1),
    this.recast = false,
    this.description,
  });
}

在 Dart 2.0 之前

是的,有!

下面是一个例子:

class Ability {
  final String name;
  final Duration effectDuration;
  final bool recast;
  final String description;

  Ability({
    @required this.name,
    this.effectDuration = new Duration(seconds: 1),
    this.recast = false,
    this.description,
  }): 
    assert(name != null),
    assert(effectDuration != null);
}

您不必断言 name 不等于 null,但它可能对您有用。

尽管您可以使用已接受的答案中描述的 flutter foundation包,但是当我使用不需要了解 Flutter 的模型类时,我更喜欢直接使用meta包。 这样它就不会对框架产生不必要的依赖。 这允许您甚至在 Flutter 之外共享 Dart 代码。

添加到pubspec.yaml

dependencies:
  meta: ^1.1.7

将其导入到您的类文件中:

import 'package:meta/meta.dart';

在代码中使用@required注释:

class Person {
  String name;
  int age;

  Person({@required this.name, this.age,});
}

所以name是必需参数,但age不是。

final person = Person(name: 'Bob');

更新:

在即将发布的 Dart 版本中,默认情况下应添加required关键字,因此根本不需要导入。

从具有空安全性的 2.12 开始,您可以使用required关键字(不是@required )。 也不需要导入任何额外的包。

在此命名参数例如name是可选的,而effectDurationrecast是必需的。

class Ability {
  final name;
  final effectDuration;
  final recast;

  Ability({this.name, required this.effectDuration, required this.recast});
}

更新pubspec.yaml ,例如:

environment:
  sdk: ">=2.12.0-0  <3.0.0"

参考资料:

  1. 声音零点安全
  2. @required 与新的 required 关键字相比如何?

具有空安全性:

  • 不可为空的命名参数:

    您需要将命名参数标记为required或提供默认值,甚至将其标记为late 例如:

     class Foo { final int a; final int b; late final int c; // Mark late and provide value later. Foo({ required this.a, // Mark required. this.b = 0, // Provided a default value. }); }
  • 可为空的命名参数:

    你不需要任何特殊的东西来处理它们。

     class Foo { final int? z; Foo({ this.z, }); }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM