Я хочу создать более специализированный список в дротике. Я не могу напрямую расширить List. Каковы мои варианты?
Как продлить список в дротике?
Ответ 1
Существует класс ListBase в dart: collection. Если вы расширяете этот класс, вам нужно только реализовать:
-
get length
-
set length
-
[]=
-
[]
Вот пример:
import 'dart:collection';
class FancyList<E> extends ListBase<E> {
List innerList = new List();
int get length => innerList.length;
void set length(int length) {
innerList.length = length;
}
void operator[]=(int index, E value) {
innerList[index] = value;
}
E operator [](int index) => innerList[index];
// Though not strictly necessary, for performance reasons
// you should implement add and addAll.
void add(E value) => innerList.add(value);
void addAll(Iterable<E> all) => innerList.addAll(all);
}
void main() {
var list = new FancyList();
list.addAll([1,2,3]);
print(list.length);
}
Ответ 2
Чтобы сделать класс реализующим Список, есть несколько способов:
- Расширение ListBase и реализация
length
,operator[]
,operator[]=
иlength=
:
import 'dart:collection';
class MyCustomList<E> extends ListBase<E> {
final List<E> l = [];
MyCustomList();
void set length(int newLength) { l.length = newLength; }
int get length => l.length;
E operator [](int index) => l[index];
void operator []=(int index, E value) { l[index] = value; }
// your custom methods
}
- Смешайте ListMixin и реализуйте
length
,operator[]
,operator[]=
иlength=
:
import 'dart:collection';
class MyCustomList<E> extends Base with ListMixin<E> {
final List<E> l = [];
MyCustomList();
void set length(int newLength) { l.length = newLength; }
int get length => l.length;
E operator [](int index) => l[index];
void operator []=(int index, E value) { l[index] = value; }
// your custom methods
}
- Делегирование другому
List
с помощьюDelegatingList
из пакета колчана:
import 'package:quiver/collection.dart';
class MyCustomList<E> extends DelegatingList<E> {
final List<E> _l = [];
List<E> get delegate => _l;
// your custom methods
}
- Делегирование другому
List
с помощьюDelegatingList
из пакета сбора:
import 'package:collection/wrappers.dart';
class MyCustomList<E> extends DelegatingList<E> {
final List<E> _l;
MyCustomList() : this._(<E>[]);
MyCustomList._(l) :
_l = l,
super(l);
// your custom methods
}
В зависимости от вашего кода каждый из этих вариантов имеет свои преимущества. Если вы переносите/делегируете существующий список, вы должны использовать последний вариант. В противном случае используйте одну из двух первых опций в зависимости от вашей иерархии типов (миксин, позволяющий расширить другой объект).
Ответ 3
A new way of extending classes was В Dart 2.6 появился новый способ расширения классов..
Теперь вы можете создать extension
из List
следующим образом:
extension MyCustomList<T> on List<T> {
// Any methods you want can be added here.
}
Методы, которые вы добавляете , могут использоваться неявно, т.е. вы можете просто использовать их на любом List
, когда у вас есть импортированный extension
.
Вот пример из спецификации функции:
extension MyFancyList<T> on List<T> {
int get doubleLength => this.length * 2;
List<T> operator-() => this.reversed.toList();
List<List<T>> split(int at) =>
<List<T>>[this.sublist(0, at), this.sublist(at)];
List<T> mapToList<R>(R Function(T) convert) => this.map(convert).toList();
}
Вы можете использовать этих новых участников на любом List
, например, как это:
const list = <String>['some', 'elements'];
list.doubleLength; // Evaluates to 4.