no-image

DartでListやMapを拡張する

これで詰まっている人を定期的に見かけるので。ここではListを例に説明する。MapやSet、Iterableについても同様の方法で拡張できる。

Listをimplementsする

もっとも単純な方法がこれだろう。Dartでは全てのクラスが暗黙のインターフェイスを持っているので、Listインターフェイスを勝手に実装してしまえばいい。ただしメンバが大量に存在する。相手は死ぬ。

class MyList<E> implements List<E> {
  // ひたすら実装していく
}

ListBaseをextendsする

dart:collectionライブラリにはListBaseという便利なクラスがある。ListBaseを継承すれば、

  • get length
  • set length
  • []
  • []=

の4つを実装するだけでListの実装が完成する。その他のメンバはこの4つの組み合わせだけで実装できるという寸法だ。

当然、MapBaseSetBaseでは実装すべきメンバが異なるので、公式のドキュメントなり、IDEの出すヒントなりを参考にしよう。

import 'dart:collection';

class MyList<E> extends ListBase<E> {
  int length;
  E operator[](int idx) => 0;
  void operator[]=(int idx, E value) { value; }
}

ただし、4つのメンバだけを使って他の全てを実装するので、あまり効率が良くない部分も出てくる。特にaddやaddAllなどは実行効率が悲惨なので、単に可変長Listをラップするだけの目的でListBaseを使用するのはやめた方がいいだろう。そういう利用シーンを想定しているなら、自前でaddやaddAllをオーバーライドするか、collectionパッケージに含まれるDelegatingListを使おう。

ListMixinを使用する

ListBaseにはmixin版も用意されている。ListBaseと特に違いは無い。

class MyList<E> extends Object with ListMixin<E> {
  int length;
  E operator[](int idx) => 0;
  void operator[]=(int idx, E value) { value; }
}