Дартс несколько верхних границ

Мне нужно реализовать решение, используя дженерики, которые реализуют 3 интерфейса, но, насколько я могу судить, дженерики в дротике поддерживают только 1 верхнюю границу?

У меня есть модель, которая выглядит так:

abstract class Category implements Built<Category, CategoryBuilder>, Identifiable, Mapable {
   ...
}

Содержимое трех интерфейсов на самом деле не имеет значения, и я пытаюсь создать класс, который может обрабатывать это в общей форме.

Я хочу что-то вроде этого:

abstract class BaseDB<T extends Built<T, R> & Identifiable & Mapable, R extends Builder<T, R>> {
   process(T entity) {
      print(entity.id); // From Identifiable
      entity.toMap(); // From Mapable
      // ... etc
   }
}

Я знаю, что это возможно как в Typescript, так и в Java, но я новичок в Dart. Кто-нибудь знает?

Забавно, это ТОЧНО моя проблема, я также пытаюсь абстрагировать БД с интерфейсом Identifiable для id и использую build_value.

Michel Feinstein 23.09.2020 10:31

Это очень быстро стало сложным и нечитаемым (как я упоминал в своем ответе ниже). Закончилось просто кастингом на dynamic в нескольких местах. Обманчиво, но в конечном итоге легче читать и поддерживать.

DarkNeuron 23.09.2020 14:41

Да, я пытался этого избежать, но, прочитав ваш опыт, я собираюсь это сделать.

Michel Feinstein 23.09.2020 18:36

(На самом деле я бросил это на Identifiable, но да, то же самое).

Michel Feinstein 23.09.2020 18:55
1
4
954
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В Дарте это невозможно. Вы можете установить только одну границу для переменной типа.

Граница переменной типа Dart используется для проверки того, какие операции вы можете выполнять с объектом типа параметра типа. Пример:

String something<T extends num>(T value) {
  return value.abs().toString();
}

Вам разрешено вызывать abs() на value, потому что мы знаем, что все экземпляры value являются числами, а num имеет метод abs.

Если вы можете написать <T extends Foo & Bar>, то в системе типов Dart нет простого типа, который может описывать объекты типа T. В Dart нет типы перекрестков (тип пересечения Foo & Bar будет супертипом всех типов, которые являются подтипами как Foo, так и Bar, а также подтипом Foo и Bar). Если Foo объявляет Baz method(), Bar объявляет Qux method() и value имеет тип T, каков тип value.method()? (Это было бы либо запрещено, либо тип был бы Baz & Qux). Это показывает, что разрешение & в границах переменных типа пропускает типы пересечения в оставшуюся систему типов, и поскольку Dart не имеет типов пересечения, он также не имеет множественных границ для переменных типа.

Когда вы объявляете класс FooBar, реализующий как Foo, так и Bar, у вас возникает одна и та же проблема: вам нужно выяснить, что возвращает method. Тем не менее, язык требует вы должны записывать это решение в свой класс, чтобы найти некоторый допустимый тип возвращаемого значения для FooBar.method, потому что в противном случае объявление класса FooBar недействительно. От пользователя требуется найти решение, чтобы «найти подкласс как Baz, так и Qux».

Хороший ответ. Я знаю, что вы, вероятно, можете связать иерархию классов, чтобы она содержала необходимые методы, но это кажется слишком сложным и многословным. В настоящее время я получаю доступ к .id и .toMap() с помощью простого приведения с использованием (entity as dynamic).id, но на самом деле это не оптимально.

DarkNeuron 02.05.2019 15:24

Другие вопросы по теме