为了清楚起见,我想在 Dart 中使用命名参数。我该如何处理它们?
I want to use named parameters in Dart for clarity. How should I handle them?
TL;DR:由于 a conscious design choice,命名参数是可选的。在没有官方语言支持的情况下,有什么方法可以强制(和通知)所需的命名参数吗?
我发现在定义 class 时使用命名参数非常有用。以 MMORPG 中的 Ability
为例:
class Ability {
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
effectDuration
和 recast
都携带相同类型的信息(即持续时间)并且可能由相同的数据类型表示。很容易搞混哪个号码去哪里。但是,它们都是对对象的正确性至关重要的信息,因此在实例化过程中不能丢失它们。
我可以通过 try-catch 来中断程序以强制执行这些参数的要求,但是对于使用 class 并且不知道(阅读不足)的人来说,这听起来并不有趣文档并直观地理解 class 的作用)它们是必需的。
有没有什么方法可以强制执行某些命名参数的要求,同时设法通知调用者所述要求and/or帮助他们正确使用它?
meta 包提供了 DartAnalyzer 支持的 @required
注解。
Flutter 经常使用它并直接从 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
// ...
}
[更新] 新 as-of Dart 2.0
在 dart 2.0 中,required
关键字已作为 null-safety 更新的一部分添加到语言中。这意味着您得到的是 compiler-enforced non-null 值,而不是分析器检查的值;这使得空检查完全多余。
这意味着此代码实际上与下面的旧代码相同,除了您永远不必担心断言作为 name
、effectDuration
和 [= 的值抛出15=] 不能为空。
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);
}
您不必断言名称不等于 null,但它可能对您有用。
虽然您可以按照接受的答案中的描述使用 flutter foundation
包,但当我使用不需要了解 Flutter 的模型 classes 时,我更喜欢使用meta 包直接。这样它就不会对框架产生不必要的依赖。这允许您甚至在 Flutter 之外共享 Dart 代码。
将meta添加到pubspec.yaml:
dependencies:
meta: ^1.1.7
将其导入您的 class 文件:
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
是可选的,而 effectDuration
和 recast
是必需的。
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"
参考文献:
空安全:
不可为 null 的命名参数:
您需要标记命名参数 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,
});
}
如果你想声明一个空变量但里面有方法,你可以:
1)使用late
关键字
2) 尽可能声明类型 null
返回示例:int? number;
3)初始化变量为空,例如:
List listOfNumbers = [];
Map mapOfPerson1 = {};
所以你可以使用变量的方法来添加它们的值
TL;DR:由于 a conscious design choice,命名参数是可选的。在没有官方语言支持的情况下,有什么方法可以强制(和通知)所需的命名参数吗?
我发现在定义 class 时使用命名参数非常有用。以 MMORPG 中的 Ability
为例:
class Ability {
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
effectDuration
和 recast
都携带相同类型的信息(即持续时间)并且可能由相同的数据类型表示。很容易搞混哪个号码去哪里。但是,它们都是对对象的正确性至关重要的信息,因此在实例化过程中不能丢失它们。
我可以通过 try-catch 来中断程序以强制执行这些参数的要求,但是对于使用 class 并且不知道(阅读不足)的人来说,这听起来并不有趣文档并直观地理解 class 的作用)它们是必需的。
有没有什么方法可以强制执行某些命名参数的要求,同时设法通知调用者所述要求and/or帮助他们正确使用它?
meta 包提供了 DartAnalyzer 支持的 @required
注解。
Flutter 经常使用它并直接从 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
// ...
}
[更新] 新 as-of Dart 2.0
在 dart 2.0 中,required
关键字已作为 null-safety 更新的一部分添加到语言中。这意味着您得到的是 compiler-enforced non-null 值,而不是分析器检查的值;这使得空检查完全多余。
这意味着此代码实际上与下面的旧代码相同,除了您永远不必担心断言作为 name
、effectDuration
和 [= 的值抛出15=] 不能为空。
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);
}
您不必断言名称不等于 null,但它可能对您有用。
虽然您可以按照接受的答案中的描述使用 flutter foundation
包,但当我使用不需要了解 Flutter 的模型 classes 时,我更喜欢使用meta 包直接。这样它就不会对框架产生不必要的依赖。这允许您甚至在 Flutter 之外共享 Dart 代码。
将meta添加到pubspec.yaml:
dependencies:
meta: ^1.1.7
将其导入您的 class 文件:
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
是可选的,而 effectDuration
和 recast
是必需的。
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"
参考文献:
空安全:
不可为 null 的命名参数:
您需要标记命名参数
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, }); }
如果你想声明一个空变量但里面有方法,你可以:
1)使用late
关键字
2) 尽可能声明类型 null
返回示例:int? number;
3)初始化变量为空,例如:
List listOfNumbers = [];
Map mapOfPerson1 = {};
所以你可以使用变量的方法来添加它们的值