Мне нужно реализовать решение, используя дженерики, которые реализуют 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. Кто-нибудь знает?
Это очень быстро стало сложным и нечитаемым (как я упоминал в своем ответе ниже). Закончилось просто кастингом на dynamic в нескольких местах. Обманчиво, но в конечном итоге легче читать и поддерживать.
Да, я пытался этого избежать, но, прочитав ваш опыт, я собираюсь это сделать.
(На самом деле я бросил это на Identifiable, но да, то же самое).
В Дарте это невозможно. Вы можете установить только одну границу для переменной типа.
Граница переменной типа 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, но на самом деле это не оптимально.
Забавно, это ТОЧНО моя проблема, я также пытаюсь абстрагировать БД с интерфейсом
Identifiableдляidи использую build_value.