Dart: не переопределяет generi c метод имеет тип параметра generi c, аналогичный типу возвращаемого значения - PullRequest
1 голос
/ 04 апреля 2020

У меня есть проблема переопределить метод generi c из абстрактного класса.

Вот мой абстрактный класс:

abstract class A {
  String getData<Type>(Type key);
}

, когда я создал класс (B) для реализовать класс (A), как показано ниже:

class B implements A {
  @override
  String getData<String>(String key) {     //Error <= B.getData' ('String Function<String>(String)') isn't a valid override of 'A.getData' ('String Function<Type>(Type)')

    return "";
  }
}

Показанная ниже ошибка компиляции в методе (getData):

'B.getData' ('String Function (String) ') не является корректным переопределением A.getData (' String Function (Type) '). dart (invalid_override)

И эта ошибка в операторе возврата:

Значение типа 'String не может быть возвращено из метода' getData ', поскольку оно имеет возвращаемый тип 'String'.

Меня смущает, почему я получаю эту ошибку, связанную с переопределением, когда тип generi c похож на тип возвращаемого значения. например, когда я создал другой класс (C) с getData<int>(int key) вместо getData<String>(String key), все работает как положено:

class C implements A {
  @override
  String getData<int>(int key) {

    return "";
  }
}

Также с классом (B), если я удалил возвращаемый тип, как показано ниже все будет работать как положено:

class B implements A {

  @override
  getData<String>(String key) {

     return "";
  }
}

Это проблема в дизайне дротиков, поэтому я могу знать об этом, потому что такого поведения нет, например, в c# языке?

DartPad Link: https://dartpad.dev/ebc7e6361d0cf1c6afad2f52ab8ebcaa

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Подпись метода

String getData<Type>(Type key);

Как правило, будет записана с T вместо Type, поскольку Type уже имеет значение .

String getData<T>(T key);

Эта подпись предназначена для метода, который позволяет заполнять любой тип для T. Это означает, что каждый подкласс должен иметь метод, который позволяет любой тип T.

Я подозреваю, что вы хотите, чтобы подклассы были специализированы для один тип generi c - в этом случае вы хотите переместить шаблон c с уровня метода на уровень класса.

abstract class A<T> {
  String getData(T key);
}

class B implements A<String> {
  @override
  String getData(String key) => '';
}

class C implements A<int> {
  @override
  String getData(int key) => '';
}
1 голос
/ 06 апреля 2020

Первый метод, который вы написали, это generic c для параметра типа с именем Type и имеет тип возврата String. То есть, это функция, которая для любого типа Type возвращает что-то типа String.

Второй метод, это generi c для параметра типа с именем String, и возвращает что-то из тип параметра типа. Тот факт, что параметром типа является с именем String, создает впечатление, что у вас есть один и тот же тип возврата в первом и во втором методе, но это не так. Первый метод имеет возврат к String. Второй метод имеет возвращаемый тип «переменная типа, которая была только что введена и имеет имя String». Эти два типа не связаны, поэтому переопределение недопустимо. Если вы переименуете переменную типа во втором методе в T, вы получите следующий эквивалентный метод:

class B implements A {
  @override
  T getData<T>(T key) {
    return "";
  }
}

, и теперь должно быть понятно, почему ваше переопределение недопустимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...