void main() {
const validId = 'a52f5a6d7b46bffe9f5ec08f';
const invalidId = 'thisisnotavalidid';
// student1 throws no errors at development time, compile time, or runtime
final student1 = Student(id: validId, fullName: 'Jimmy Beans');
// student2 throws no errors at development time, but throws an
// AssertionError (in debug mode) at runtime when trying to
// instantiate Student() with an invalid id.
final student2 = Student(id: invalidId, fullName: 'Bimmy Jeans');
print(student1.toString());
}
// 24 hexadecimal characters
const String studentIdPattern = r'^[a-f\d]{24}$';
class Student {
final String id;
final String fullName;
Student({
required this.id,
required this.fullName,
}) : assert(RegExp(studentIdPattern, caseSensitive: false).hasMatch(id));
@override
toString() {
return "Instance of 'Student': {id: $id, fullName: $fullName}";
}
}
Run this code on DartPad 基本上,我们为24个字符的十六进制字符串声明了一个正则表达式模式r'^[a-f\d]{24}$'(它可以在student.dart库/文件中,也可以在一些配置文件中),并以assert()函数调用的形式向默认的Student()构造函数添加一个初始化器。 当调用Student()构造函数时,初始化器首先运行,并检查传入的id参数是否有效。 关于您的具体示例的一些附加说明:
3条答案
按热度按时间ryhaxcpt1#
原始答案(见下面的更新):这在Dart的语言级别上是不可能的--不过有几个替代方案。
您可以简单地定义一个枚举沿着一个方法来从枚举中派生一个字符串:
更新2:在Dart 3中,我们还有另一种方法,使用密封类:
https://dart.dev/language/class-modifiers#sealed
旧更新:现在Dart 2.17支持在枚举上声明方法,可以比我最初的答案更干净地做到这一点:
或者你可以定义一个有三个命名构造函数的类,并重写toString方法:
bakd9h0s2#
在Dart中强制自定义类型的另一种方法是在构造函数中使用Assert(当使用自定义类型时)。
初始化器(构造函数末尾冒号之后的部分)在构造函数本身之前执行,因此可以在那里对构造函数变量进行自定义要求。
我们使用Assert而不是异常,因为Assert抛出的错误是我们希望在生产之前在代码中捕获的错误,而不是我们希望在运行时处理的异常。
假设我们有一个名为
Student
的类,它有一个名为id
的必填字段。id
的数据类型是String
,* 但 * 我们希望强制执行一个规则,即学生ID必须是24个字符的十六进制字符串。就像你说的,TypeScript中的自然选择是使用字符串文字或template literal创建一个自定义类型,并在函数 * 和 * 中使用学生ID时将其用作参数类型。Dart不允许我们以同样的方式创建自定义数据类型(尽管有typedef类型别名),但它允许我们在尝试使用数据类型时对数据类型的 * 值 * 进行Assert。
Run this code on DartPad
基本上,我们为24个字符的十六进制字符串声明了一个正则表达式模式
r'^[a-f\d]{24}$'
(它可以在student.dart库/文件中,也可以在一些配置文件中),并以assert()
函数调用的形式向默认的Student()
构造函数添加一个初始化器。当调用
Student()
构造函数时,初始化器首先运行,并检查传入的id
参数是否有效。关于您的具体示例的一些附加说明:
r'^(HELLO)|(WORLD)$'
*
assert()
调用可以在代码中的其他地方进行在这里String
类型的值是什么很重要;它不必在初始化器中。Map<KeyClass, ValueClass>
作为“自定义类型”,并以与TypeScript类型相当的方式使用KeyClass
和ValueClass
的枚举或类,但对于简单的模式来说,这是多余的。lrl1mhuk3#
是的,现在您可以使用
2.13
dart版本的typedefs
https://dart.dev/language/typedefs