这是我的课,
class Animal{
Animal();
}
class Mammal extends Animal{
String name;
Mammal(this.name):super();
}在我的主要方法里,
main() {
Animal dog = new Mammal("Tommy");
if(dog is Mammal)
print(dog.name); //prints "Tommy"
}我的狗对象有动物类型,它怎么能暴露哺乳动物的财产“名字”?Dartpad本身就是自动的--建议我使用“name”属性。
威尔,它从动物类型上升到哺乳动物,因为我确信狗对象是哺乳动物,一旦它进入if语句。但在幕后是如何运作的呢?
发布于 2021-06-21 15:16:54
您所描述的特性称为“类型提升”,它只发生在编译器能够证明它有效的地方。
例如:
void function(Animal animal) {
if (animal is Mammal) {
// animal now has a static type of Mammal
print(animal.name); // safe to access Mammal-only fields
}
}void function() {
Animal animal = Mammal('name');
if (animal is Mammal) {
// animal now has a static type of Mammal
}
}但是,它不适用于:
Animal animal = Mammal('name');
void function() {
if (animal is Mammal) {
// animal still has static type Animal
}
}class Foo {
Animal animal;
void function() {
if (animal is Animal) {
// animal still has a static type of Animal
}
}
}这是因为Dart的getter语法。在Dart中,可以使用以下语法定义getter:
Foo get foo {
return makeSomeFoo();
}事实上,尽管大多数人认为“getter是类似于字段的函数”,但实际上恰恰相反:字段自动生成相应的getter。这意味着类型提升不能用于任何字段访问在概念上可能是getter的地方。
因为局部变量和函数参数没有“覆盖getter”的概念,所以它们是安全的。
但是,想象一下下面的顶级getter:
Animal get animal {
if (Random().nextBool()) return Mammal('name');
else return Reptile('name');
}仅仅因为对animal的第一个调用返回了一个Mammal,并不意味着后续的调用总是会这样,所以假设animal现在是一个Mammal是不安全的。
类似的逻辑适用于类,并增加了getter可以覆盖字段的复杂性。
注意,通过使用局部变量,可以轻松地解决实例成员和顶级getter的问题:
Animal get animal => // some implementation
void function() {
final _animal = animal;
if (_animal is Animal) {
print(_animal.name); // totally safe
}
}发布于 2021-06-21 08:30:19
我找到了答案,这就是所谓的智能铸造。Dart可以自动对局部变量进行转换,如果它在保证变量类型的条件语句中。
https://stackoverflow.com/questions/68064529
复制相似问题