「Groovy イン・アクション」を読んでる。今 56 ページ だ。
ここで、演算子のオーバーライドの例が載っている。でダックタイピングって思ったのは、加算演算子がそうなのかなと。
本に載ってたコードの一部抜粋。
class Money { private int amount private String currency Money (amountValue, currencyValue) { amount = amountValue currency = currencyValue } Money plus (Money other) { if (null == other) return null if (other.currency != currency) { throw new IllegalArgumentException("cannot add $other.currency to $currency") } return new Money(amount + other.amount, currency) } } def buck = new Money(1, 'USD') assert buck + buck == new Money(2, 'USD') assert buck - buck == new Money(0, 'USD') // minus メソッドを実装していないので、実行時に例外が発生する。
plus ってメソッドを定義していたら、+演算子が使用出来る。minus ってメソッドを定義していたら、-演算子が使用出来る。
これって、ダックタイピング だよね?
assert buck + buck == new Money(2, 'USD')
ここは、内部的には、buck.plus(buck) 変換されるんだと思う、んで Money クラスは 「たまたま」plus メソッドが実装されてたから問題無い。
でも、
assert buck - buck == new Money(0, 'USD') // minus メソッドを実装していないので、実行時に例外が発生する。
ここは、内部的には、buck.minus(buck) に変換されて、Money クラスは minus メソッドが実装されていないから実行時例外が発生する。
C# の場合、演算子のオーバーロードを行うには、その型に static なメソッドを実装する必要がある。※チェック処理とかは省いてます。
public static Money operator + (Money m1, Money m2)
{
return new Money(m1.amount + m2.amount, m1.currency);
}
でも、Groovy の場合は、インスタンスが plus って操作を実行出来て、それを簡潔に記述するのに +演算子を使って表現するって形だと理解してる。(シンタックスシュガーって言うんだっけ?)
オブジェクト指向っぽい解決方法なのかな。
※関係無いけど、演算子のオーバーライドって違和感がある。これは、本書(「Groovy イン・アクション」P56)にも載ってた。
厳密な意味では加算演算子はオーバーライドされているわけではありません。〜(省略)このケースでは演算子実装が最も適切な表現でしょう。