Home > Blockchain >  Dart extended classes with generic types won't use the direct parent type
Dart extended classes with generic types won't use the direct parent type

Time:09-30

I have 2 classes (B and C) and I am trying to create a parent type A so I can manipulate a variable a of type A. The following example works fine:

class A {}

class B extends A {}

class C extends A {}

var b = true;

final A a = b ? C() : B();

But for some reason, when A has a generic type A<T>, it doesn't work

class A<T> {}

class B extends A<int> {}

class C extends A<String> {}

var b = true;

final A a = b ? C() : B(); // <- Error

I get the linting error:

A value of type 'Object' can't be assigned to a variable of type 'A<dynamic>'. Try changing the type of the variable, or casting the right-hand type to 'A<dynamic>'.dart(invalid_assignment)

What is the reason? And can I make it work without an explicit cast as A?

CodePudding user response:

Dart's UP algorithm, which is used to find an common supertype when needed, is not that clever. (For various reasons, including being too clever might cause it to never terminate in some cases).

Here the expression b ? C() : B() tries to find a common supertype of the types C and B. Their immediate super-interfaces are just A<int> and A<String> respectively, which are unrelated types. Neither is a subtype of the other, so neither can be used as common supertype. Their immediate super-interfaces are both just Object, and thus we have a solution. So, UP(B, C) is Object, and that's the type of b ? C() : B(). (This is actually not from the linked document, the UP algorithm on those types falls through to the least-upper-bound algorithm of the current language specification, which gives the result Object).

You might have expected the algorithm to find A<Object> instead. All I can say is that it won't. The algorithm will only look at the types that are actually implemented by the two types being compared, where A<String> and A<int> are different unrelated types, and A<Object> is not actually among the interfaces implemented by either type. Their only common implemented type is Object.

  • Related