Home > Back-end >  Why doesn't this Dart code with generic classes and constraints compile?
Why doesn't this Dart code with generic classes and constraints compile?

Time:01-18

I can't understand why this code doesn't compile. In my intentions, the following snippet should declare a BaseGenericClass with no constraint on its argument, and a GenericClass deriving from BaseGenericClass with a constraint on type T telling the compiler to accept only classes derived from AbstractArgClass.

abstract class BaseGenericClass<T> {
  final T _arg;
 
  BaseGenericClass(this._arg);
}

class GenericClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
  GenericClass() : super(ArgClass());
}

abstract class AbstractArgClass {}

class ArgClass extends AbstractArgClass {}

ArgClass derives from AbstractArgClass, still lines 8 raises this error: The argument type 'ArgClass' can't be assigned to parameter type 'T'

CodePudding user response:

I think the compiler is correct here. ArgClass and AbstractArgClass in fact do not extend T, and I can't see a way to tell them that T is meant to be ArgClass.

It should work if you change it like this:

class GenericClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
  GenericClass(T t) : super(t);
}

You have to supply your instance of ArgClass to the constructor of GenericClass:

final g = GenericClass(ArgClass());

If you do not want to provide this from ouside, you can add a static function to make a new instance, like:

class GenericClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
  GenericClass._(T t) : super(t);

  static GenericClass make() => GenericClass._(ArgClass());
}

and get an instance:

final g = GenericClass.make();

CodePudding user response:

Ber's answer apparently works around the problem introducing a sort of intermediation... I tried to create a useless IntermediateClass that just introduces the restrictions on the type T (T has to derive from AbstractArgClass). This works!!! AnotherGenericClass, as expected, does not compile because AnotherClass does not extend AbstractArgClass.

Still the question: why? It looks like a compiler glitch to me, do you agree?

abstract class BaseGenericClass<T> {
  final T _arg;
  
  BaseGenericClass(this._arg);
}

class IntermediateClass<T extends AbstractArgClass> extends BaseGenericClass<T> {
  IntermediateClass(T arg) : super(arg);
}

class GenericClass extends IntermediateClass {
  GenericClass() : super(ArgClass());  
}

abstract class AbstractArgClass {}

class ArgClass extends AbstractArgClass {}

class AnotherClass {}

class AnotherGenericClass extends IntermediateClass {
  AnotherGenericClass() : super(AnotherClass());
}
  • Related