悪い子のためのDart講座〜メソッドを実行時に追加する〜
いつの間にやら、GoogleからDartという言語が発表されました。
世間の評判を見てみると、一部の方々からは
「無難な感じで刺激が足りない」
「クラスベースが気に食わない。JavaScriptみたいに実行時にプロパティを追加したい」
などといった意見も出ているようです。
そこで本エントリでは、刺激を求める方々のために、
Dartで実行時にメソッドを追加する方法を紹介します。
まずはこちらのコードを御覧ください。
main() { var i = new Flexible(); i.addMethod("plus1", (self, n) { return n + 1; }); i.addMethod("wawa", (self, x, y) { return self.plus1(x) + self.plus1(y); }); var x = i.plus1(99); print(x); // => 100 var y = i.wawa(23, 103); print(y); // => 128 }
実行時にメソッドが追加できているのが確認できます。
これでJavaScript信者の方々も、少しは心やすらぐかと思います。
メソッドaddMethodを持つクラスFlexibleの定義は次のようになっています。
class Flexible { var methods; Flexible() : methods = new Map(); addMethod(name, fun) { methods[name] = fun; } noSuchMethod(name, args) { if (methods[name] == null) { throw new NoSuchMethodException(this, name, args); } else if (args.length == 0) { return methods[name](this); } else if (args.length == 1) { return methods[name](this, args[0]); } else if (args.length == 2) { return methods[name](this, args[0], args[1]); } throw new NotImplementedException(); } }
methodsという変数を用意しておき、コンストラクタで空のMapに初期化します。
addMethodはmethodsに引数で渡された関数を追加するだけです。
noSuchMethodは存在しないメソッドを起動した際に呼ばれる特殊なメソッドで、
ここでaddMethodで追加した関数をディスパッチしてやるという訳です。
パラメータが2つの場合までしか対応していなかったり、
厳密に言えばメソッドを追加しているわけではなかったり、
見れば見るほど卑怯なコードですが、動けばいいんですよ。動けば。
とはいったものの、このコードはstandalone VMでしか動きません。
コンパイラはどうもnoSuchMethodの対応をしていないような気がします。
また、上のソースではnoSuchMethodは2引数ですが、仕様では1引数です。
本当は仕様通り書きたいところですが、それが動く環境がないようなのでやむなしです。
VMのソースを見たら「あとで仕様に合わせる」というコメントが書いてあるので、
そのうち仕様通りに書けば、動くようになってくれるでしょう。
そんなわけで、Dartもその気になれば実行時にメソッドを追加することができます。
皆さんも是非お試しください。おすすめしませんが。