Seth Ladd
Seth Ladd

Reputation: 120679

How do I extend a List in Dart?

I want to create a more specialized list in dart. I can't directly extend List. What are my options?

Upvotes: 47

Views: 20430

Answers (6)

Christian Findlay
Christian Findlay

Reputation: 7692

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];
}

Upvotes: 2

Aditya Joardar
Aditya Joardar

Reputation: 594

    //list is your given List and iterable is any object in dart that can be iterated
    list.addAll(Iterable)

Upvotes: -3

Colin
Colin

Reputation: 91

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!

Upvotes: 9

creativecreatorormaybenot
creativecreatorormaybenot

Reputation: 126824

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.

Upvotes: 25

Alexandre Ardhuin
Alexandre Ardhuin

Reputation: 76273

To make a class implement List there are several ways :

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
}
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
}
import 'package:quiver/collection.dart';

class MyCustomList<E> extends DelegatingList<E> {
  final List<E> _l = [];

  List<E> get delegate => _l;

  // your custom methods
}
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).

Upvotes: 48

Seth Ladd
Seth Ladd

Reputation: 120679

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);
}

Upvotes: 28

Related Questions