In Dart, how can a subclass extend a superclass, having a generic type of the subclass extend a type of the superclass?

Viewed 3662

This is a Dart Generics question. This question is simpler then it seems, please keep reading.

I have:

  • class SomeController uses type T
  • class ExtendedController uses type S
  • ExtendedController extends SomeController
  • S extends T.

The below code doesn't work:

import 'package:flutter/material.dart';

class SomeValue {}

class ExtendedValue extends SomeValue {}

abstract class SomeController<T extends SomeValue> extends ValueNotifier<T> {
  SomeController(T value) : super(value);

  factory SomeController.create() {
    return ExtendedController();
  }
}

class ExtendedController extends SomeController<ExtendedValue> {
  ExtendedController() : super(ExtendedValue());
}

I get the error :

The return type 'ExtendedController' isn't a 'SomeController<T>', as defined by the method 'create'.

in the return ExtendedController(); line.

I then changed it to this:

import 'package:flutter/material.dart';

class SomeValue {}

class ExtendedValue extends SomeValue {}

abstract class SomeController<T extends SomeValue> extends ValueNotifier<T> {
  SomeController(T value) : super(value);

  factory SomeController.create() {
    return ExtendedController();
  }
}

class ExtendedController<S extends ExtendedValue> extends SomeController<S> {
  ExtendedController() : super(ExtendedValue());
}

Still doesn't work, but now I get another error: The constructor returns type 'ExtendedValue' that isn't of expected type 'S'.

this time in the super(ExtendedValue()); line.

2 Answers

Let's take the first error: The return type 'ExtendedController' isn't a 'SomeController<T>', as defined by the method 'create'.

It is telling ExtendedController is not an expected return type from create method as per definition.

create is a factory method here it and expects the return type to be SomeController

factory SomeController.create() {
  return SomeController();
}

We cannot change like this also as SomeController is an abstract class. So, I moved the factory method to ExtendedController.

class SomeValue {}

class ExtendedValue extends SomeValue {}

abstract class SomeController<T extends SomeValue> extends ValueNotifier<T> {
  SomeController(T value) : super(value);
}

class ExtendedController extends SomeController {
  ExtendedController(ExtendedValue value) : super(value);

  factory ExtendedController.create() {
    return ExtendedController(ExtendedValue());
  }
}

Hope my explanation helps up to some extent.

Related