为什么Dart不能推断或记住我的财产类型?

lrl1mhuk  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(113)

此问题在此处已有答案

Smart cast (automatic type promotion) using 'is' is not working(2个答案)
27天前关闭。
在检查Dart中对象的属性是否属于特定的子类型之后,Dart似乎无法推断/知道/记住属性todo在代码中的子类型。
例如,如果我检查state.todoTodo_hasChildren类型,然后使用state.todo作为Todo_hasChildren类型,我会得到一个Dart分析错误(“参数类型'Todo 3'不能分配给参数类型'Todo3_hasChildren'”)。
我知道如何解决这个问题(使用as关键字进行转换或将属性分配给自己的变量),但为什么它不知道类型?这是Dart演变中的临时性还是永久性的?

class MyState {
  final Todo todo;

  MyState(this.todo);
}

void doStuff(MyState state) {
  if (state.todo is Todo_hasChildren) //
    processHasChild(state.todo);
}

void processHasChild(Todo_hasChildren todo) {}

字符串

jgovgodb

jgovgodb1#

原因实际上是MyState类的子类可能会用getter覆盖该字段,而getter并不总是给予相同的值。如下所示:

class MyState2 extends MyState {
  MyState2(super.todo);

  @override
  Todo get todo => Random().nextBool() ? Todo_hasChildren() : someOtherTodo();
}

字符串
现在,当使用MyState2调用doStuff时,类型检查可能会在第一次通过,但当为processHasChild获取类型检查时,它可能会返回错误的类型。
你可以尝试这个完整的程序,看看自己,它偶尔崩溃,因为这一点:

import 'dart:math';

void main() {
    doStuff(MyState2(Todo()));
}

class Todo{}
class Todo_hasChildren extends Todo{}

class MyState2 extends MyState {
  MyState2(super.todo);
    @override
    Todo get todo => Random().nextBool() ? Todo_hasChildren() : Todo();
}

class MyState {
    final Todo todo;

    MyState(this.todo);
}

void doStuff(MyState state) {
    if (state.todo is Todo_hasChildren) {
        processHasChild(state.todo as Todo_hasChildren);
    }
}

void processHasChild(Todo_hasChildren todo) {}

avwztpqn

avwztpqn2#

因为todostate的一个属性,Dart只能在从局部变量提升类型时才能推断出类型。这与可空类型提升非常相似。参见:使用可空字段。
所以你必须这样做:

void doStuff(MyState state) {
  final todo = state.todo;
  if (todo is Todo_hasChildren) //
    processHasChild(todo);
}

字符串

相关问题