野次馬エンジニア道

野次馬な気持ちでプログラミングをあれこれと綴ります

JavaScriptでオブジェクト指向 (2) - 継承

前回は、クラスの定義の方法をまとめた。

StringとObjectの関係

継承関係にあるStringとObjectを見直してみる。

var foo = new String();
foo instanceof String // true
String.prototype instanceof Object // true

String.prototypeがObjectのインスタンスとなる関係に注目する。

プロトタイプで継承

自分で継承関係を作る場合も同じ事をしてやればよい。

function SubClass(){}
var foo = SubClass();
SubClass.prototype = new BaseClass();

が、constructorプロパティに問題がある。prototypeを上書きしてしまっているので、 foo.constructor == BaseClassとなる。仕方がないので

SubClass.prototype.constructor = SubClass;

とする。

より良いアプローチ

一見よさそうだが、もしSubClass.prototypeを変更した場合、親クラスや兄弟のクラスも影響を受ける。一時的なconstructorを挟んでやる。

var F = function(){};
F.prototype = BaseClass.prototype;
SubClass.prototype = new f();
SubClass.prototype.constructor = SubClass;

親クラスへのアクセス・メソッドの呼び出し

Javaのsuperにあたるものは無い。ので自前で用意するのが良い。

SubClass.__super__ = BaseClass.prototype;
SubClass.prototype.test = function(arg){
 var ret = SubClass.__super__.test.call(this, args); // call or applyで呼ぶ
 return ret;
}

以上の継承の処理を関数に

親クラス・子クラスに共通の処理としてまとめられる。

function extend(SubClass, BaseClass) {
 var F = function(){};
 F.prototype = BaseClass.prototype;
 SubClass.prorotype = new F();
 SubClass.prototype.constructor = SubClass;
 SubClass.__super__ = BaseClass.prototype;
}

実際にはライブラリやフレームワークを利用することが多いはず。 例えばBackbone.jsではBackbon.jsのextendの仕組み - The Dabsong Conshirtoeの素晴らしい説明が参考になる。

次回はプロパティからアクセス制御。