しおしお

IntelliJ IDEAのことなんかを書いてます

Dartの拡張関数を使ってみる

Dartの拡張関数とは

Kotlinと同じような感じで、既存のクラスに対して関数追加できちゃう感じですね。 ドキュメントはこちら→(Extension methods | Dart)

構文

extension onを使って拡張したい型に対して、拡張関数を定義してあげます。 extensiononの間に任意の名前を指定することで、別名をつけることもできるみたいですね。

extension <extension name> on <type> {
  (<member definition>)*
}

拡張関数を試してみる

パターン1

extension onStringを指定することで、Stringに対して拡張関数を追加できますね。 拡張関数は、通常の関数と同じように呼び出すことができますね。

void main() {
  print("hoge".hello());
}

extension on String {
  String hello() {
    return "hello, ${this}";
  }
}

実行結果

$ dart extension-sample.dart
hello, hoge

パターン2

Generics対応したListに対しても拡張関数を追加できるか確認してみます。 この例だと、List<String>に対しては拡張関数を呼び出せますが、List<int>に対しては呼び出すことができません。

void main() {
  var ints = ['1', '2'].toInt();
  print(ints);

}

extension on List<String> {
  List<int> toInt() {
    return this.map((e) => int.parse(e)).toList();
  }
}

実行結果

$ dart list-extension.dart
[1, 2]

拡張関数名が衝突した場合…

スコープ内に同じ名前の拡張関数が存在知る場合は、こんな感じのビルドエラーとなります。 この例だと、Stringに対して追加した拡張関数のhogeが複数存在しているよって感じですね。

※同一スコープ内で名前衝突が起こるような拡張関数を生やすことって無いと思いますが…

Error: The method 'hoge' is defined in multiple extensions for 'String' and neither is more specific.
Try using an explicit extension application of the wanted extension or hiding unwanted extensions from scope.

衝突を回避するために

extension onじに、別名をつけてあげることで回避できるようです。 拡張関数を使う際には、別名の型に事前に変換してから呼び出す感じになるようです。

void main() {
  String2('').hoge();
}

extension String2 on String {
  void hoge() {
    print('hoge');
  }
}