After checking if a property of an object in Dart is of a particular subtype, Dart doesn't seem to infer / know / remember that the property todo
is of that subtype further down in the code.
For example, if I check state.todo
is of type Todo_hasChildren
and then later use state.todo
as a Todo_hasChildren
type, I get a Dart analysis error ("The argument type 'Todo3' can't be assigned to the parameter type 'Todo3_hasChildren'")
I know how to fix this (convert using the as
keyword or assign the property to its own variable) but why does it not know the type? Is this temporary in the evolution of Dart or is this something that is permenant?
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) {}
The reason is actually that subclasses of your MyState
class may override the field with a getter that doesn't consistently give the same value back. Like this:
class MyState2 extends MyState {
MyState2(super.todo);
@override
Todo get todo => Random().nextBool() ? Todo_hasChildren() : someOtherTodo();
}
Now, when calling doStuff
with a MyState2
the type check might pass the first time but when getting it for the processHasChild
it might return the wrong type.
You can try out this full program to see for yourself that it occasionally crashes because of this:
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) {}