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());
CodePudding user response:
Dart has a system called type promotion, where it can promote the type of a variable, similar to type inference.
It works as a cast. On the first example you've explicit promoted the type of your list to be of type A
, so there's nothing strange about this.
Take a look at the first article that explains this mechanism.
CodePudding user response:
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.