'How to conditionally cast a type in dart?

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.



Solution 1:[1]

This is a Dart limitation. You can check the reason in this issue (thanks, jamesdlin).

Instantiating the Animal subclass inside each if block can be cumbersome, in case you have lots of conditions.

I would do, instead:

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();
}

Solution 2:[2]

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);
  }
}

Solution 3:[3]

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();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Miguel de Sousa
Solution 3 BambinoUA