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());
}