在Dart 2.6.0中,当我使用is
测试类成员变量的类型时,条件代码块不会推断类型。
在以下代码中,方法show1()
产生错误,“未为类'C1'定义吸气剂's2'。”同时,方法show2()
可以很好地编译。
class C1 {
C1(this.s1);
String s1;
}
class C2 extends C1 {
C2(String s1, this.s2) : super(s1);
String s2;
}
class InferenceTest {
InferenceTest(this.c);
C1 c;
void show1() {
print(c.s1);
if (c is C2) print(c.s2); // error
}
void show2(C1 c) {
print(c.s1);
if (c is C2) print(c.s2); // no error
}
}
这似乎是一个错误,但似乎我也不应该第一个注意到这一点。我在尝试从小部件状态对widget.myValue
使用推论时遇到了问题。
我找到了错误,还是我不了解某些内容?
(我发现在Java之类的多线程环境中这是合理的,因为c
的值可能会在is
测试和使用c
之间改变。但是我理解Dart在很大程度上假设一个线程。)
答案 0 :(得分:3)
Dart不会类型提升实例变量,只能是局部变量。
当您测试局部变量具有特定类型时,程序可以使用该变量,就好像它具有经过测试的类型一样...有一些警告,因为该语言需要绝对确定该值不会改变在测试和使用之间。例如,在测试保护的范围内,不得对变量进行任何分配,并且对闭包中捕获的变量也不得进行任何分配。因为变量是局部变量,所以编译器可以向自己保证这足以确保变量值不变。
类c
的实例变量InferenceTest
的类型为C1
。在某些有效程序中,c
的值可以在测试c is C2
和用法c.s2
之间更改,并且可以通过完全不同的库中的代码对其进行更改,因此该语言不会在这种情况下敢于进行类型提升。因此,c
访问权限下的C1
类型仍然是c.s2
,您将无法访问s2
。
如果要促销,请尝试将值移动到局部变量:
var c = this.c;
if (c is C2) print(c.s2);
这可行,这也是您在show2
方法中看到的,因为函数参数是局部变量,因此可以进行类型提升。