Xtendに触ってみる その7 続・拡張メソッド

拡張メソッドについては以前紹介しました。

が、Xtendの拡張メソッドを説明する上で外せない、大事なことを書きわすれていました。
拡張メソッドは、そのクラスで定義したもの以外に別のクラスで定義したものをインポートして使用することができます。その方法には以下の2通りがあります。

まずはstatic importでstaticメソッドを拡張メソッドとして使えるようにする方法。static importにextensionキーワードを追加します。

import static extension java.util.Collections.*

val list = newArrayList(1, 2, 3)

// Collections#maxが拡張メソッドとして使える
val max = list.max

もう1は任意のクラスで定義したメソッドを拡張メソッドとして使えるようにする方法。こちらは拡張メソッドとしてインポートしたいメソッドを定義したクラスをextensionキーワード付きのフィールドとして宣言します。このとき、DIコンテナと組み合わせてフィールドをDIするようにしておくことで拡張メソッドの実装を差し替えることができる、という点がポイントです(ちなみにXtendではGuiceが推奨されているようです)。

class MyClass {

  /**
   * StringExtensionsで定義されたメソッドを
   * 拡張メソッドとして使えるようにする
   */
  @Inject
  extension StringExtensions extensions
 
}

ユーティリティ的なメソッドはstaticメソッドでもよさそうですが、基本的にはextensionフィールドを利用して実装を差し替えられるようにしておくのがよさそうです。
Xtendの拡張メソッドは関数をメッセージ伝達モデルのシンタックスで呼び出すためのシンタックシュガーというだけでなく、言語レベルで関数の実装を差し替えるための仕組みが用意されているのは面白いですね。