最近のプログラミング言語にはオペレータ(+
とか-
みたいなやつ)を上書きして独自の機能を提供することができたりします。
Haxeでも抽象型を利用することで、オペレータを上書きする機能が利用出来ます。
例えば、Dateクラスの抽象型を作って、+
オペレータをオーバーロードすることで、
date + n
とすればn日後の日付が取得出来るようになります。
abstract AbsDate(Date) from Date to Date {
@:op(A + B) public inline function add(step: Int): AbsDate {
return Date.fromTime(this.getTime() + (864000000 * step));
}
public inline function concretization(): Date {
return this;
}
}
class Main {
static function main() {
var date: AbsDate = new Date(2016, 1, 1, 0, 0, 0);
trace(date); // Mon Feb 01 2016 00:00:00 GMT+0900 (JST)
trace(date + 1); // Tue Feb 02 2016 00:00:00 GMT+0900 (JST)
trace(date + 2); // Wed Feb 03 2016 00:00:00 GMT+0900 (JST)
trace(date + 3); // Thu Feb 04 2016 00:00:00 GMT+0900 (JST)
}
}
このような感じでオブジェクトのドメインに対して意味を持つオペレータを定義することが出来るようになります。
ちょっと残念なのは、抽象型では抽象元となるクラスのメソッドは所持していないため、
抽象元となったクラスのメソッドを呼びたい場合に、具象化してあげなければなりません。
上記のサンプルではconcretization
というメソッドを持たせて実現していますが、
この他に、抽象元となった型を指定した変数に代入することでも元のクラスを取得することが出来ます。
var date: AbsDate = new Date(2016, 1, 1, 0, 0, 0);
// メソッドをチェーンするならこんな感じ
trace((date + 1).concretization().getTime()); // Tue Feb 02 2016 00:00:00 GMT+0900 (JST)
// 代入で型を解決するとこんな感じ
var next_date: Date = date + 1;
trace(next_date.getTime()); // Tue Feb 02 2016 00:00:00 GMT+0900 (JST)
抽象元のメソッドも呼べた
@musou1500 より@:forward
使えばいけるとの金言頂きました。
やった!
@:forward abstract AbsDate(Date) from Date to Date {
@:op(A + B) public inline function add(step: Int): AbsDate {
return Date.fromTime(this.getTime() + (864000000 * step));
}
}
class Main {
static function main() {
var date: AbsDate = new Date(2016, 1, 1, 0, 0, 0);
trace((date + 1).getTime()); // 1455116400000
}
}
オブジェクトに対してオペレーターの意味が変わるというのは、新しい言語を生み出しているような感覚でなかなか楽しいものです。
適切に活用していきたい機能ですね。