2011年11月11日金曜日

JavaScriptでオープンクラス


最近もっぱら、JavaScriptの勉強を行なっています。
今日は、JavaScriptにもオープンクラスが存在したことに対する備忘録です。

Rubyistにとっては当たり前の機能として存在する「オープンクラス」

PHPerやJavaプログラマーには聞きなれない概念ですが、
ひとことで言うと、「既存のクラス定義を任意のタイミングで変更可能」な機能です。
今更確認することでもないのですが、Rubyの場合は単純に
以下のように既存クラスの定義を変更できるかとおもいます。

class Array

  def tail
    last(length-1)
  end

end

scalaのListに存在する[tail]メソッド(先頭以外の要素からなるListを返す)
をrubyの組み込みクラスである[Array]クラスに追加して見ました。

このような仕組みがJavaScriptでも実現できます。

var arr = [1, 2, 3];

// last()を実行(そんな関数は存在しない)
arr.last();  // TypeError: Object 1,2,3 has no method 'last'

// Arrayクラスに変更を加える
Array.prototype.last = function() { return this[this.length-1]; }

// メソッドが追加された
arr.last();  // 実行結果 [3]


JavaScriptはブラウザ間の挙動の差に泣かされ、いままで避けれるだけ避けてきましたが、
Node.jsやTituniumなどのブラウザの世界を超えてJavaScriptが活躍し始めた所で逃げるのをやめることにしました。
勉強をすすめるうちに、なかなかどうして楽しい言語だと気付かされます。
とりあえず、JavaScriptはprototypeをきちんと学ぶと、色々できることが最近分かって来ました。
ん~、かなり面白いです。


=================================

おまけとして、少し話題に出てきたScalaでオープンクラスを実現する方法

Scalaは静的型付け言語のため、オープンクラスというものは機能として存在しません。
しかし、暗黙的型変換を利用することによって、同等のことが実現可能です。

ScalaのListクラスの[head]メソッドと同等のメソッド[h]を作成してみます。

class List2[T](xs : List[T]){ 
  def h: T = xs.head
}

implicit def list2List2(xs: List[Any]) = new List2(xs)

val l = List(1, 2, 3, 4, 5)
l.h // res1: Any = 1

ListクラスがList2に暗黙的な型変換が行われ、メソッド[h]がエラーなく実行されているのが
わかるかと思います。

0 件のコメント:

コメントを投稿