tl;dr
Replace multiple field accesses by a local variable.
final house = House()..animal = Dog()
final animal = house.animal;
if (animal is Dog) {
animal.bark();
} else if (animal is Cat) {
animal.meow();
} else if (animal is Wolf) {
animal.howl();
}
Complete answer
This is a Dart limitation. It happens because the compiler cannot guarantee that the result of the first access to animal
is the same as the second access. Even is the field is final, a subclass may override its getter to change the return value at different accesses.
Check the adapted example below from Leaf Petersen. (Thanks @jamesdlin for mentioning.)
class A {
final num x = 3;
}
class B extends A {
num y = 3;
num get x => y;
}
void main() {
B b = B();
A a = b;
if (a.x is int) {
b.y = 3.0;
(a.x as int).isEven; // Fall down go boom.
}
}
One way to work around that is by avoiding multiple field accesses. This can be done by assigning the result of the field access to a local variable such as:
final house = House()..animal = Dog()
final animal = house.animal;
if (animal is Dog) {
animal.bark();
} else if (animal is Cat) {
animal.meow();
} else if (animal is Wolf) {
animal.howl();
}
Animal animal = house.animal; if (animal is Dog) { animal.bark(); }
. – Bootblack