I want to create a more specialized list in dart. I can't directly extend List. What are my options?
6 Answers
To make a class implement List there are several ways :
- Extending ListBase and implementing
length
,operator[]
,operator[]=
andlength=
:
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
}
- Mixin ListMixin and implementing
length
,operator[]
,operator[]=
andlength=
:
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
}
- Delegating to an other
List
withDelegatingList
from the quiver package:
import 'package:quiver/collection.dart';
class MyCustomList<E> extends DelegatingList<E> {
final List<E> _l = [];
List<E> get delegate => _l;
// your custom methods
}
- Delegating to an other
List
withDelegatingList
from the collection package:
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
}
Depending on your code each of those options has their advantages. If you wrap/delegate an existing list you should use the last option. Otherwise, use one of the two first options depending on your type hierarchy (mixin allowing to extend another Object).

- 3,189
- 4
- 26
- 34

- 71,959
- 15
- 151
- 132
There is a ListBase class in dart:collection. If you extend this class, you only need to implement:
get length
set length
[]=
[]
Here is an example:
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);
}

- 112,095
- 66
- 196
- 279
-
The question specifically asked about the options, could you clarify what else you can do? – Juniper Belmont Apr 27 '13 at 23:12
-
-
I guess the other two options would be to implement the List interface, or use List as a mixin. – Greg Lowe Jun 09 '13 at 23:00
-
1For performance one should usually also override (and delegate) at least `add` and `addAll`. These are heavily used methods that are much more efficient when they don't go through `length` and `[]`. See http://dartbug.com/12652. – Florian Loitsch Aug 30 '13 at 13:27
-
Just for curiosity.
would mean any kind of object? If I want to implement a List witch only accepts – Daniel Jul 04 '14 at 03:31, should I substitute all 's for ? -
Yes, use `class AppleList extends ListBase
{}` and replace all `E` by `Apple`. – Alexandre Ardhuin Jul 10 '14 at 19:09 -
So, how to define list of lists with this approach, I could not define `FancyList [FancyLists]' :( – Hasan A Yousef Mar 03 '18 at 14:33
-
Another point, is there a way to convert my `List` to `FancyList`, something I can develop like `.toFancyList` or so! – Hasan A Yousef Mar 03 '18 at 15:33
A new way of extending classes was introduced with Dart 2.6.
You can now create an extension
of List
like this:
extension MyCustomList<T> on List<T> {
// Any methods you want can be added here.
}
The methods you add can be used implicitly, i.e. you can just use them on any List
when you have your extension
imported.
Here is an example from the feature specification:
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();
}
You can use these new members on any List
, e.g. like this:
const list = <String>['some', 'elements'];
list.doubleLength; // Evaluates to 4.

- 114,516
- 58
- 291
- 402
The answers to this are pretty outdated, and I'm in the process of doing this for my own project, so I thought I'd help some people out by posting a really clean answer that doesn't involve any overriding or implementing of things.
The quiver package has an extendable List class called DelegatingList that makes extending a list trivial.
class FruitList extends DelegatingList<Fruit> {
final List<Fruit> _fruits = [];
List<Fruit> get delegate => _fruits;
// custom methods
}
Hopefully this helps someone who comes across this question like I did!

- 71
- 1
- 1
-
This worked for me, however `DelegatingList` also appears to be available in `package:collection` which I already had in my project, so I didn't need the `quiver` dependency. – Mrb83 May 11 '23 at 08:49
Following on from the answer above, you can create an immutable list like this:
class ImmutableList<E> extends ListBase<E> {
late final List<E> innerList;
ImmutableList(Iterable<E> items) {
innerList = List<E>.unmodifiable(items);
}
@override
int get length => innerList.length;
@override
set length(int length) {
innerList.length = length;
}
@override
void operator []=(int index, E value) {
innerList[index] = value;
}
@override
E operator [](int index) => innerList[index];
}

- 6,770
- 5
- 51
- 103
//list is your given List and iterable is any object in dart that can be iterated
list.addAll(Iterable)

- 580
- 5
- 11
> definition. Is it possible to skip redefining the getters and setters and delegate to super?
– relet May 03 '19 at 03:42