我发现了一些奇怪的行为,试图检查Dart中某些对象的运行时类型。 让我们举一个简单的例子:
main(List<String> args) {
List<Map> l1 = new List<Map>();
l1.add(new Map<String, int>());
List<int> l2 = ['Start', 'Stop'];
checkType(l1.runtimeType);
checkType(l1[0].runtimeType);
checkType(l2.runtimeType);
}
checkType(Type type) {
switch(type) {
case List:
print('it is a List!');
break;
case Map:
print('it is a List!');
break;
default:
print('Unmanaged type $type');
break;
}
}
此程序具有以下输出:
非托管类型List<Map>
非托管类型_InternalLinkedHashMap<String, int>
非托管类型List
无法在switch语句中检查第一种情况,因为如果我尝试设置“List<Map>
”情况,我会收到错误:在常量表达式中,此运算符的操作数必须为'num'类型“
第二个不能匹配,因为在一个案例中使用_InternalLinkedHashMap会得到以下错误:案例表达式必须是常量。
在最后一种情况下,我将List定义为整数列表(List<int>
),但系统忽略它并将其视为一个简单的List。
我认为这是误导性的,这样的声明应该是禁止的。
任何帮助/建议?
答案 0 :(得分:4)
如果你想根据对象的类型进行流控制,你实际上想要根据对象的类是否实现接口而不是它的运行时类型来实现。这就是类型测试运算符 is
和is!
的用途。
请记住,在Dart中,类也是一个接口,因此您可以测试对象是否是特定类。
class Something {
...
}
var s = new Something();
print(s is Something); // true
请注意,我们倾向于将其视为“类”(例如List
和Map
)不是类,而是接口。任何返回此类实例(包括构造函数)的东西实际上都会返回一个实现该接口的类。
你可以使用泛型,但要小心。
void main() {
var a = [1, 2, 'three'];
print(a is List); // True
print(a is List<int>); // True!!!!
print(a is List<String>); // True!!!!
var b = new List<int>.from([1, 2, 3]);
print(b is List); // True
print(b is List<int>); // True
print(b is List<String>); // False
}
类可以通过显式实现它,从实现它的类继承,或通过混合来实现接口。
class Base {
void a() {}
}
class Mix {
void b() {}
}
class Mixed extends Base with Mix {}
class Explicit implements Base {
void a() {}
}
void main() {
var c = new Mixed();
print(c is Mixed); // True
print(c is Base); // True
print(c is Mix); // True
var d = new Explicit();
print(d is Base); // True
}