JSシミュレーションクラス継承
4010 ワード
//最後のパラメータはJSONが示すクラス定義
//パラメータが1より大きい場合、最初のパラメータはベースクラスであり、そうでない場合、ベースクラスはobjectである
//中間のパラメータはクラス実装のインタフェース
//戻り値はクラス、クラスは構造関数であり、ベースクラスのprototypeを継承します.
function Class(){
aDefine = arguments[arguments.length - 1];//入力された最後のパラメータは定義するクラスです
if(!aDefine) return;//パスパラメータを使用しない場合は、そのまま終了します.
var aBase = arguments.length>1?arguments[0]:object;//伝達されるパラメータが1より大きい場合、最初のパラメータはベースクラスであり、1に等しい場合、ベースクラスのデフォルトはobjectである
function prototype_(){};//プロトタイプチェーンを接続するprototype一時関数の作成
prototype_.prototype = aBase.prototype;
var aPrototype = new prototype_();//クラスで使用するプロトタイプオブジェクトの作成
for(var member in aDefine){
if(aDefine[member]!='Create'){//コンストラクション関数はプロトタイプチェーンに掛けなくても、コンストラクション関数は最終的に返されます.
aPrototype[member] = aDefine[member];
}
}
//クラスの設定
if(aDefine.Create){//コンストラクション関数がある場合
var aType = aDefine.Create;//クラスはこのコンストラクタです
}else{//コンストラクション関数がなければ
var aType=function(){//デフォルトのコンストラクタの作成
this.base.apply(this, arguments);//親クラスのコンストラクション関数を呼び出す
}
}
aType.prototype = aPrototype;//クラス(コンストラクション関数)のプロトタイプの設定
aType.Base = aBase;//タイプ関係の設定
aType.prototype.Type = aType;//オブジェクトのタイプを判断するために、このクラスのオブジェクトにType属性を拡張します.
return aType;//プロトタイプ継承を加えたコンストラクション関数を返すとnewになります
}
function object(){};//最も基本的な方法と属性を実現するためにobjectルートクラスを定義します.
object.prototype.isA=function(type){//オブジェクト属性が何らかのタイプに属しているか否かを判断
var self = this.Type;
while(self){
if(self == type){
return true;
}
self = self.Base;
}
return false;
}
object.prototype.ベースクラスのコンストラクタを呼び出す
var Caller = object.prototype.base.caller;//この関数を呼び出す関数を取得
Caller && Caller.Base && Caller.Base.apply(this, arguments);
//Callerが存在しCaller.ベースが存在する場合はCallerを呼び出す.ベースメソッド
//若果CallerまたはCaller.ベースには存在しない文があるので、後の文は実行しなくてもいいです.
}
var people=Class({//peopleクラスの定義
Create: function(name, age){
this.base();
this.name = name;
this.age = age;
},
say: function(){
console.log('My name is ' + this.name + ",I'm "+ this.age + '.');
}
})
var chinaPeople = Class(people,
{
Create: function(name, age, country){
this.base(name, age);
this.country = country;
},
sayCountry: function(){
console.log('My country is ' + this.country);
}
}
)
var man1 = new people('kaka', 32);
var man2 = new chinaPeople('kaka', 32, 'china');
man2.say(); //My name is kaka,I'm 32.
man2.sayCountry(); //My country is china
callerはoperaブラウザをサポートしていないのでbaseメソッドを書き換える
object.prototype.base = function(){
var Base = this.Type.Base;//現在のオブジェクトのベースクラスの取得
if(!Base.Base){//ベースクラスがない場合
Base.apply(this, arguments);//ベースクラスコンストラクタを直接呼び出す
}else{
this.base = MakeBase(Base);//まずこれを複写します.base
Base.apply(this, arguments);
delete this.base;//複写baseプロパティの削除
};
function MakeBase(Type){
var Base = Type.Base;
if(!Type.Base)return Base//ベースクラスにベースクラスがないので、包装する必要はありません
return function(){//一時変数Baseを参照する閉パッケージ関数としてパッケージ
this.base = MakeBase(Base);//まずこれを複写します.base
Base.apply(this, arguments);//ベースクラスコンストラクタを呼び出す
}
}
}
//パラメータが1より大きい場合、最初のパラメータはベースクラスであり、そうでない場合、ベースクラスはobjectである
//中間のパラメータはクラス実装のインタフェース
//戻り値はクラス、クラスは構造関数であり、ベースクラスのprototypeを継承します.
function Class(){
aDefine = arguments[arguments.length - 1];//入力された最後のパラメータは定義するクラスです
if(!aDefine) return;//パスパラメータを使用しない場合は、そのまま終了します.
var aBase = arguments.length>1?arguments[0]:object;//伝達されるパラメータが1より大きい場合、最初のパラメータはベースクラスであり、1に等しい場合、ベースクラスのデフォルトはobjectである
function prototype_(){};//プロトタイプチェーンを接続するprototype一時関数の作成
prototype_.prototype = aBase.prototype;
var aPrototype = new prototype_();//クラスで使用するプロトタイプオブジェクトの作成
for(var member in aDefine){
if(aDefine[member]!='Create'){//コンストラクション関数はプロトタイプチェーンに掛けなくても、コンストラクション関数は最終的に返されます.
aPrototype[member] = aDefine[member];
}
}
//クラスの設定
if(aDefine.Create){//コンストラクション関数がある場合
var aType = aDefine.Create;//クラスはこのコンストラクタです
}else{//コンストラクション関数がなければ
var aType=function(){//デフォルトのコンストラクタの作成
this.base.apply(this, arguments);//親クラスのコンストラクション関数を呼び出す
}
}
aType.prototype = aPrototype;//クラス(コンストラクション関数)のプロトタイプの設定
aType.Base = aBase;//タイプ関係の設定
aType.prototype.Type = aType;//オブジェクトのタイプを判断するために、このクラスのオブジェクトにType属性を拡張します.
return aType;//プロトタイプ継承を加えたコンストラクション関数を返すとnewになります
}
function object(){};//最も基本的な方法と属性を実現するためにobjectルートクラスを定義します.
object.prototype.isA=function(type){//オブジェクト属性が何らかのタイプに属しているか否かを判断
var self = this.Type;
while(self){
if(self == type){
return true;
}
self = self.Base;
}
return false;
}
object.prototype.ベースクラスのコンストラクタを呼び出す
var Caller = object.prototype.base.caller;//この関数を呼び出す関数を取得
Caller && Caller.Base && Caller.Base.apply(this, arguments);
//Callerが存在しCaller.ベースが存在する場合はCallerを呼び出す.ベースメソッド
//若果CallerまたはCaller.ベースには存在しない文があるので、後の文は実行しなくてもいいです.
}
var people=Class({//peopleクラスの定義
Create: function(name, age){
this.base();
this.name = name;
this.age = age;
},
say: function(){
console.log('My name is ' + this.name + ",I'm "+ this.age + '.');
}
})
var chinaPeople = Class(people,
{
Create: function(name, age, country){
this.base(name, age);
this.country = country;
},
sayCountry: function(){
console.log('My country is ' + this.country);
}
}
)
var man1 = new people('kaka', 32);
var man2 = new chinaPeople('kaka', 32, 'china');
man2.say(); //My name is kaka,I'm 32.
man2.sayCountry(); //My country is china
callerはoperaブラウザをサポートしていないのでbaseメソッドを書き換える
object.prototype.base = function(){
var Base = this.Type.Base;//現在のオブジェクトのベースクラスの取得
if(!Base.Base){//ベースクラスがない場合
Base.apply(this, arguments);//ベースクラスコンストラクタを直接呼び出す
}else{
this.base = MakeBase(Base);//まずこれを複写します.base
Base.apply(this, arguments);
delete this.base;//複写baseプロパティの削除
};
function MakeBase(Type){
var Base = Type.Base;
if(!Type.Base)return Base//ベースクラスにベースクラスがないので、包装する必要はありません
return function(){//一時変数Baseを参照する閉パッケージ関数としてパッケージ
this.base = MakeBase(Base);//まずこれを複写します.base
Base.apply(this, arguments);//ベースクラスコンストラクタを呼び出す
}
}
}