I have an abstract class ImageUpdate
. Two classes, NewImage
and ExistingImage
implement ImageUpdate
.
I have a variable imageUpdates
of type List<ImageUpdate>
.
When I try adding a variable of type NewImage
to the List, I get this error:
Unhandled Exception: type 'NewImage' is not a subtype of type 'ExistingImage' of 'value'
I am pretty stumped, since the list is of ImageUpdate
and not ExistingImage
, so I have no idea how to debug it, especially since Dart is type safe (nowhere am I using dynamic
).
Any help would be appreciated, thanks.
CodePudding user response:
I suspect that you have code similar to:
class Base {}
class Derived1 extends Base {}
class Derived2 extends Base {}
List<Base> makeList() {
var list = [Derived1()];
return list;
}
void main() {
var list = makeList();
list.add(Derived2()); // TypeError
}
What happens is that the List
object is originally created as a List<Derived1>
. (That is, list.runtimeType
will be something like List<Derived1>
, not its static (declared) type of List<Base>
.) Then, when you try to add a Derived2
object to list
, it will fail at runtime because list
's actual, runtime type is List<Derived1>
, which does not allow Derived2
elements.
This ultimately stems from Dart allowing implicit type conversions from GenericClass<Derived>
to GenericClass<Base>
if Derived
derives from Base
. This is useful in many cases, but it also can lead to situations like this one that fail at runtime.
You can fix this by explicitly stating that you want a List<Base>
object:
List<Base> makeList() {
var list = <Base>[Derived1()]; // Note the explicit type.
return list;
}
or, if that's not possible, by creating a new List<Base>
object:
var list = <Base>[...makeList()];
var list = List<Base>.from(makeList());
(In this particular situation, List.of(makeList())
also would work since it would create a new List
object with the static type, but I wouldn't use that since being explicit about the type conversion would be more readable.)