prototype.jsでの継承を楽にする

Mochikitも好きですが、普段はRails使いということもあってprototype.jsを使っています。

そういえばjavascriptのライブラリでOOなもの、ということで初めて出会ったのはjsolaitでした。 当時の印象としては「んー確かにがんばってるんだけど・・・ちょっと大げさっていうか・・・」って感じでした。

そして去年、prototype.jsに出会うわけですが「class-style OO」とうたっている部分がかなりシンプル(すぎ)で衝撃でした。

ただ、やっぱりjavascriptにおいて「継承」というのはやっかいな問題です。 というわけで誰か作ってると思うんですが、より簡単に継承できるライブラリを作ってみました。

javascript code
  1. Class.def = function(definition) {
  2.   var klass = Class.create();
  3.   if(definition.__extend__)
  4.     Class.inherit(klass, definition.__extend__);
  5.   if(definition.__static__)
  6.     Object.extend(klass, definition.__static__);
  7.   if(definition.__include__) {
  8.     if(definition.__include__.constructor != Array)
  9.       definition.__include__ = [definition.__include__];
  10.     definition.__include__.each(function(include){
  11.       Object.extend(klass.prototype, include);
  12.     });
  13.   }
  14.   ["__static__","__extend__","__include__"].each(function(n){delete definition[n];}
  15.   Object.extend(klass.prototype, definition);
  16.   return klass;
  17. }
  18.  
  19. Class.inherit = function(child, parent) {
  20.   Object.extend(child, parent);
  21.   child.__super__ = parent.prototype;
  22.   var dummy = function(){};
  23.   dummy.prototype = parent.prototype;
  24.   child.prototype = new dummy();
  25.   child.prototype.constructor = child;
  26.   return child;
  27. }
  28.  

こんだけです。 使い方はサンプルをみるほうがわかりやすいと思うので、サンプルをどーぞ。

javascript code
  1. var IncludedClass = Class.def({
  2.   __static__ : {
  3.     includedMethod : function() {
  4.       return "includedMethod:"+this.value;
  5.     }
  6.   }
  7. });
  8.  
  9. var AClass = Class.def({__include__ : IncludedClass,
  10.   __static__ : {
  11.     A : "A static"
  12.   },
  13.  
  14.   initialize : function(val) {
  15.     if(!val) throw "error";
  16.     this.val = val;
  17.     this.klass = "AClass";
  18.   },
  19.  
  20.   inspect : function() {
  21.     return "< "+this.klass+" : "+this.val+">";
  22.   }
  23. });
  24.  
  25. var BClass = Class.def({ __extend__ : AClass,
  26.   __static__ : {
  27.     B : "B static"
  28.   },
  29.  
  30.   initialize : function(val) {
  31.     BClass.__super__.initialize.call(this, val);
  32.     this.klass = "BClass";
  33.   }
  34. });
  35.  
  36. var CClass = Class.def({ __extend__ : BClass,
  37.   __static__ : {
  38.     C : "C static"
  39.   },
  40.  
  41.     initialize : function(val) {
  42.       CClass.__super__.initialize.call(this, val);
  43.       this.klass = "CClass";
  44.     }
  45. });
  46.  
  47. var a = new AClass("aaaaaaa");
  48. var b = new BClass("bbbbbbb");
  49. var c = new CClass("ccccccc");
  50. alert("a inspect:"+a.inspect()); //=> a inspect:
  51. alert("b inspect:"+b.inspect()); //=> b inspect:
  52. alert("c inspect:"+c.inspect()); //=> c inspect:
  53. alert("includedMethod:"+a.includedMethod()); //=> includedMethod:included aaaaaa
  54. alert("CClass.A:"+CClass.A); //=> CClass.A:A static
  55. alert("CClass.B:"+CClass.B); //=> CClass.B:B static
  56. alert("CClass.C:"+CClass.C); //=> CClass.C:C static
  57. alert("b.constructor = a.constructor:"+(b.constructor == a.constructor).toString()); //=>b.constructor = a.constructor:false
  58. alert("b instanceof BClass:"+(b instanceof BClass).toString()); //=>b instanceof BClass:true
  59. alert("b instanceof AClass:"+(b instanceof AClass).toString()); //=>b instanceof AClass:true
  60. alert("c instanceof BClass:"+(c instanceof BClass).toString()); //=>c instanceof BClass:true
  61. alert("c instanceof AClass:"+(c instanceof AClass).toString()); //=>c instanceof AClass:true</div>
  62.  

継承の処理がかなり楽になっていると思います。 テキトーに場当たりで単純にnewを使って継承していたりすると

「親クラスのコンストラクタに必須な引数があって、それがないとエラーでるから継承できねーよ、しゃーない適当に引数付けとくか」

ということになったりするもんですが(俺はよくなってますw)このライブラリを使えば大丈夫。 また、こんな変な書き方イヤだよ!!って方でも継承の部分はClass.inheritに独立させてあるのでそこだけつかえばオッケーです。

一応動作は確認していますがおかしいところあったら報告していただけるとありがたいです。

07.27.08/12am

About

Author:yuin(http://inforno.net/)

文学部文化学科卒という生粋の文系趣味プログラマ。

主にRuby、Javascript、PHP、JAVA,Python,C,Scala,Schemeなどを使っています。今はPythonな感じかもしれない。今後作曲活動なども復活するかもしれない。

Pages