継承
プロトタイプチェーンを以下のようにつなぐことで、メソッドの継承(のようなこと)が実現できます。
オブジェクト → 共有オブジェクト1(子クラス) → 共有オブジェクト2(親クラス)
- オブジェクトでは、子クラスや親クラスで定義した関数が使える。
- オブジェクトや子クラスで関数を定義して、親クラスの関数を上書きできる。
例:
// 親とするオブジェクトのコンストラクタ関数。 function Animal( type ) { this.type = type; } Animal.prototype = { getType: function(){ return this.type; }, isPanthera : function() { return false; } } // 子とするオブジェクトのコンストラクタ関数。 function Kitten( name ) { this.name = name; } // プロトタイプに親を指定 // 子 → 親 のプロトタイプチェーンができる Kitten.prototype = new Animal(); // 子独自の関数 Kitten.prototype.getName = function(){ return this.name; } // 子で上書きする関数 Kitten.prototype.isPanthera = function(){ return true; } // オブジェクト作成 var shiro = new Kitten( "shiro" ); // 呼び出し // -子で定義した関数 // -親で定義した関数 // -子でオーバーライドした関数 // が利用できる。 // ただし、typeはundefinedのまま。(function Animal()が実行されていないため。) stdout.innerHTML += shiro.getName() + ":" + shiro.isPanthera() + ":" + shiro.getType() + "<br/>";
親クラスのコンストラクタの呼び出し
↑では親のコンストラクタ関数が実行されず、親で定義したつもりのフィールド(type)が初期化されていません。Javaのsuper()のように親のコンストラクタを呼び出すには、次のようにします。
// typeを初期化するにはコンストラクタ関数を明示的に呼び出す。 function Tiger( name, type ) { this.name = name; // 親クラスのコンストラクタ関数を明示的に呼び出してthisを初期化する。 Animal.call( this, "tiger" ); // Animal("tiger"); ではだめ。(thisが初期化されない。) } Tiger.prototype = new Animal(); Tiger.prototype.getName = function(){ return this.name; } Tiger.prototype.isPanthera = function(){ return true; } // オブジェクト作成 var tora = new Tiger( "tora" ); stdout.innerHTML += tora.getName() + ":" + tora.isPanthera() + ":" + tora.getType() + "<br/>";