Reputation: 2214
It seems if it's just a variable, I can conditionally cast like this.
Animal animal = Dog();
if (animal is Dog) {
animal.bark(); // animal is of type Dog here
}
But if it's a property on a class, how do I conditionally cast?
House house = House()
house.animal = Dog();
if (house.animal is Dog) {
house.animal.bark(); // fail
}
I know I can do it like this
if (house.animal is Dog) {
Dog animal = house.animal;
animal.bark();
}
But that seems cumbersome. Is there anyway I can check and cast type in one go like I can with variables?
Thanks a lot.
Upvotes: 9
Views: 4650
Reputation: 8447
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();
}
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();
}
Upvotes: 13
Reputation: 7100
Maybe it is better solution to use interfaces.
abstract class Animal {
void doSound(); // each animal does sound
}
class Dog implements Animal {
@override
void doSound() {
print('wof');
}
}
class Cat implements Animal {
@override
void doSound() {
print('meow');
}
}
House house = House()
house.animal = Dog();
animal.doSound();
house.animal = Cat();
animal.doSound();
Upvotes: 0
Reputation: 303
You can manage a conditional type cast like the example below:
class MyException implements Exception {
int customCode = 2;
}
void myFunc(){
//you can switch between the values below to see the effect
// throw Exception();
throw MyException();
}
void main() {
try {
myFunc();
} catch (e) {
final i = e is MyException ? e.customCode : -10;
print(i);
}
}
Upvotes: 0