'Type safety in Dart using Container
I found something strange in dart. If there is a list that contains instances of a base class (in this example Super), the list can be set with a list of inherited instances. It seems that this changes the list type at runtime.
Is this intended behavior or is this a bug in Dart?
abstract class Super {}
class A extends Super {}
class B extends Super {}
class Container {
List<Super> mylist = [];
Container(this.mylist);
}
void main() {
// 1. dont't works
final container = Container(<A>[A(), A()]);
// 2. works
final container = Container([A(), A()]);
print(container.mylist.runtimeType);
container.mylist.add(B());
print(container.mylist);
}
If case 1 is used in the code above I get the following error:
JSArray<A>
Uncaught Error: TypeError: Instance of 'B': type 'B' is not a subtype of type 'A'
The error is at the line where I try to add an instance of B:
container.mylist.add(B());
Solution 1:[1]
When you do:
final container = Container(<A>[A(), A()]);
you explicitly create a List<A> object. Although Container's constructor expects a List<Super>, it accepts a List<A> argument because Dart considers Generic<Derived> to be a subtype of Generic<Base> if Derived is a subtype of Base. Your later attempt to do container.mylist.add(B()); will fail because container.mylist is actually a List<A> and therefore cannot legally store any B elements.
When you instead do:
final container = Container([A(), A()]);
then, because the List literal is not given an explicit type, its type is inferred to be List<Super> from Container's expected construction parameter. container.mylist.add(B()); will succeed since container.mylist is actually a List<Super> and therefore can legally store B elements.
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 |
