我尝试编写以下代码,但 T 只能是 int、double 或自定义类。我找不到如何在 Dart 中限制类型或像 C# 中那样工作的东西。如何在 Dart 中做到这一点?
class Array3dG<T> extends ListBase<T> {
List<T> l = List<T>();
Array3dG(List<T> list) {
l = list;
}
set length(int newLength) { l.length = newLength; }
int get length => l.length;
T operator [](int index) => l[index];
void operator []=(int index, T value) { l[index] = value; }
}
在编译时约束类型变量。一个类型变量上只能有一个绑定,并且唯一同时满足int
和自定义类的边界是 Object
。
正如 @Mattia 所建议的,您可以在运行时检查并抛入构造函数,如果类型参数不是您提供的参数之一:
Array3dG(this.list) {
if (this is! Array3dG<int> &&
this is! Array3dG<double> &&
this is! Array3dG<MyClass>) {
throw ArgumentError('Unsupported element type $T');
}
}
这可以防止创建错误的实例,但不会在编译时捕获它。
另一种选择是使用工厂方法而不是构造函数:
class Array3dG<T> {
List<T> list;
Array3dG._(this.list);
static Array3dG<int> fromInt(List<int> list) => Array3dG<int>._(list);
static Array3dG<int> fromDouble(List<double> list) => Array3dG<double>._(list);
static Array3dG<MyClass> fromMyClass(List<MyClass> list) => Array3dG<MyClass>._(list);
...
}
然后用作Array3dG.fromInt(listOfInt)
.它看起来像一个命名构造函数,但它只是一个静态工厂方法(所以前面没有使用new
(。
您可以在运行时使用 is
关键字检查类型:
Array3dG(List<T> list) {
if (list is List<int>) {
//Handle int
}
else if (list is List<double>) {
//Handle double
}
else if (list is List<MyClass>) {
//Handle MyClass
}
else {
throw ArgumentError('Unsupported $T type');
}
}
请注意,如果您以相同的方式处理int
和double
,则可以检查num
您可以在此处查看联合类型的进度:https://github.com/dart-lang/sdk/issues/4938