JavaScript継承方式(1)

4866 ワード

この間、JS OOの書き方を紹介しましたが、この記事からJS OOの継承方法を見てみましょう.
オブジェクト向けの言語の多くは継承をサポートしており、継承の最も重要な利点はコード多重化であり、大規模なソフトウェアシステムを構築することである.クラスが別のクラスの属性やメソッドを再利用できる場合は、継承と呼ばれます.この角度からJSの継承方式を見てみましょう.JSでの継承方式は書き込み方式と密接に関係している.異なる書き込み方式は異なる継承方式をもたらす.様々な流行のJSライブラリの継承方法もそれぞれ異なります.最も簡単な多重化から開始します.
 
1、コンストラクタ方式書き込みクラス、メソッド呼び出しにより親属性/フィールドを子にコピーして継承を実現
ここでは親クラス、子クラスは構造関数で書かれており、プロトタイプは使用されません.サブクラスは、親関数を呼び出して親のプロパティをコピーします.
/**
 *   Polygon:   
 * @param {Object} sides
 */
function Polygon(sides) {
	this.sides = sides;
	this.setSides = function(s) {this.sides=s;}
}

/**
 *   Triangle:   
 */
function Triangle() {
	this.tempfun = Polygon;//              tempfun
	this.tempfun(3);//  
	delete this.tempfun;//     
	this.getArea = function(){};
}

//new    
var tri = new Triangle();
console.log(tri.sides);//     
console.log(tri.setSides);//     
console.log(tri.getArea);//     

//     Triangle      instanceof   Polygon  false
console.log(tri instanceof Triangle);//true
console.log(tri instanceof Polygon);//false

JavaScriptの名前付き関数の複数の呼び出し方法のため、サブクラスは以下のような多様な実装形態を有することもできる.サブクラスで親を呼び出す方法が異なるだけです.
function Triangle() {
	Polygon.call(this,3); //call      
	this.getArea = function(){};	
}
function Triangle() {
	Polygon.apply(this,[3]); //apply      
	this.getArea = function(){};
}
function Triangle() {
	var temp = new Polygon(3); //new      
	for(atr in temp) { //       
		this[atr] = temp[atr];
	}	
	this.getArea = function(){};
}

この方法の欠点は、サブクラスのインスタンスオブジェクトがinstanceofで親クラスをチェックするときに常にfalseであることである.これはjavaで「is a」を継承する関係とは逆です.
 
2、プロトタイプ書き込み、プロトタイプ方式継承
core JS自身のオブジェクトシステムはプロトタイプ方式(prototype based)で継承されている.あるいはcore JSは一般的なクラス継承(class based)システムではなく,プロトタイプ継承を用いて自分のオブジェクトシステムを実現する.仕事の中で私達も原型の方式で継承を実現することができて、コードは多重して自分の機能のモジュールを構築します. 
/**
 *   Polygon:   
 * 
 */
function Polygon() {}
Polygon.prototype.sides = 0;
Polygon.prototype.setSides = function(s) {this.sides=s;}

/**
 *   Triangle:   
 */
function Triangle() {}
Triangle.prototype = new Polygon(); //           
Triangle.prototype.getArea = function(){}

//new   
var tri = new Triangle();
console.log(tri.sides);//     
console.log(tri.setSides);//     
console.log(tri.getArea);//    

//instanceof  
console.log(tri instanceof Triangle);//true,         
console.log(tri instanceof Polygon);//true,          

出力から子クラスが親クラスPolygonのプロパティsidesとメソッドsetSidesを継承していることがわかりますが、sidesは0で、どうして三角形なのでしょうか.triを呼び出さなければなりませんsetSides(3)を三角形にします.これは不便そうです.パラメータを伝達できない、すなわちプロトタイプ方式の欠点である.利点は「is a」の関係を正しく維持していることです.
 
3、組合せ構造関数/原型方式でクラスを書き、前の方式で継承する
この方式では親クラス,子クラスの属性は構造関数に掛けられ,メソッドはプロトタイプに掛けられる.
/**
 *   Polygon:   
 */
function Polygon(sides) {
	this.sides = sides;
}
Polygon.prototype.setSides = function(s) {this.sides=s;}

/**
 * Triangle    
 * @param {Object} base  
 * @param {Object} height  
 */
function Triangle(base,height) {
	Polygon.call(this,3);//         
	this.base = base;
	this.height = height;
}
Triangle.prototype = new Polygon();//         

Triangle.prototype.getArea = function(){ //         
	return this.base*this.height/2;
}

//new   
var tri = new Triangle(12,4);
console.log(tri.sides);//     
console.log(tri.setSides);//     
console.log(tri.base);//    
console.log(tri.height);//    
console.log(tri.getArea);//    

//instanceof  ,        "is a"   
console.log(tri instanceof Triangle);//true,         
console.log(tri instanceof Polygon);//true,          

 
関連:
JavaScript継承方式(2)
JavaScript継承方式(3)
JavaScript継承方式(4)