類的繼承有兩種基本方法
對象冒充 基本原理: 建構函式使用this關鍵字給所有屬性和方法賦值(建構函式實際上僅僅是賦值函數),所以可以利用一種方式,在類內部直接運行賦值函數,把其this關鍵字傳遞給新類。例如:
Java代碼
1. var a = function(){
2. this.a = 1;
3. this.b = 2;
4. alert(this);
5. }
6.
7. var b = function(){
8. this.aa = a;//對a中的this進行轉換,同樣的方式還有
9. this.aa();
10. delete this.aa; //要把這個中間方法刪除掉,否則可能會在以後的操作中覆蓋原來類的方法
11.
12. //或者
13. a.call(this,arg1,arg2);
14. //或者
15. a.apply(this,[args]);
16. }
17.
18. var ob = new b();
var a = function(){
this.a = 1;
this.b = 2;
alert(this);
}
var b = function(){
this.aa = a;//對a中的this進行轉換,同樣的方式還有
this.aa();
delete this.aa; //要把這個中間方法刪除掉,否則可能會在以後的操作中覆蓋原來類的方法
//或者
a.call(this,arg1,arg2);
//或者
a.apply(this,[args]);
}
var ob = new b();
原型鏈
基本原理:關於原型鏈,詳見(http://www.javaeye.com/topic/53537)把超類的一個執行個體付給子類的prototype對象,即可把超類的固定屬性和方法傳遞給子類,要注意一點,這種方法無法在執行個體化時傳遞參數,所以一般採用混合方式進行類的繼承。
prototype.js中的類定義和繼承
1.6.0以前:
Java代碼
1. /** obsolete syntax **/
2. var Person = Class.create(); //通過Class.create方法建立空類
3. Person.prototype = { //把方法定義到prototype中,注意,是通過initalize方法初始化類的屬性
4. initialize: function(name) {
5. this.name = name;
6. },
7. say: function(message) {
8. return this.name + ': ' + message;
9. }
10. };
11.
12. var guy = new Person('Miro');
13. guy.say('hi');
14. // -> "Miro: hi"
15. //prototype中的繼承方式:
16. var Pirate = Class.create(); //建立空類;
17. // inherit from Person class:
18. Pirate.prototype = Object.extend(new Person(), { //先執行個體化超類,再把超類中的方法複製到子類中去,
19. // redefine the speak method //注意,實際上prototype類定義機制中並沒有直接定義
20. say: function(message) { //類的屬性而是通過intilize方法,而且所有的方法都
21. return this.name + ': ' + message + ', yarr!'; //之直接定義在prototype中,所以直接用原型鏈方式
22. } //繼承超類的所有方法不會產生問題。
23. });
24.
25. var john = new Pirate('Long John');
26. john.say('ahoy matey');
27. // -> "Long John: ahoy matey, yarr!"
/** obsolete syntax **/
var Person = Class.create(); //通過Class.create方法建立空類
Person.prototype = { //把方法定義到prototype中,注意,是通過initalize方法初始化類的屬性
initialize: function(name) {
this.name = name;
},
say: function(message) {
return this.name + ': ' + message;
}
};
var guy = new Person('Miro');
guy.say('hi');
// -> "Miro: hi"
//prototype中的繼承方式:
var Pirate = Class.create(); //建立空類;
// inherit from Person class:
Pirate.prototype = Object.extend(new Person(), { //先執行個體化超類,再把超類中的方法複製到子類中去,
// redefine the speak method //注意,實際上prototype類定義機制中並沒有直接定義
say: function(message) { //類的屬性而是通過intilize方法,而且所有的方法都
return this.name + ': ' + message + ', yarr!'; //之直接定義在prototype中,所以直接用原型鏈方式
} //繼承超類的所有方法不會產生問題。
});
var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"
來看一下Class.create方法的實現代碼
Java代碼
1. var Class = {
2. create: function() {
3. return function() { //實際上把所有的屬性定義到intiliaze方法(實際上是一個類)中,
4. this.initialize.apply(this, arguments); //然後通過對象冒充方式繼承該類
5. }
6. }
7. }
var Class = {
create: function() {
return function() { //實際上把所有的屬性定義到intiliaze方法(實際上是一個類)中,
this.initialize.apply(this, arguments); //然後通過對象冒充方式繼承該類
}
}
}
可以從prototype的例子充分體會到通過對象冒充和原型鏈類繼承的差別,一般來說屬性需用對象冒充方式繼承,方法需用原型鏈方式繼承。
prototype-1.6.0以後版本:
Java代碼
1. 1.6.0以後,對prototype的類進行了更多的擴充,舉例:
2.
3. /** new, preferred syntax **/
4. // properties are directly passed to `create` method
5. var Person = Class.create({
6. initialize: function(name) { //不必定義一個空類,and定義方法的位置改變
7. this.name = name;
8. },
9. say: function(message) {
10. return this.name + ': ' + message;
11. }
12. });
13.
14. // when subclassing, specify the class you want to inherit from
15. var Pirate = Class.create(Person, { //第一個參數是class,作為超類在定義類時直接繼承
16. // redefine the speak method
17. say: function($super, message) {
18. return $super(message) + ', yarr!';
19. }
20. });
21.
22. var john = new Pirate('Long John');
23. john.say('ahoy matey');
24. // -> "Long John: ahoy matey, yarr!"
25.
26.
27.
28. //聲明子類時對子類的initialize進行重寫
1.6.0以後,對prototype的類進行了更多的擴充,舉例:
/** new, preferred syntax **/
// properties are directly passed to `create` method
var Person = Class.create({
initialize: function(name) { //不必定義一個空類,and定義方法的位置改變
this.name = name;
},
say: function(message) {
return this.name + ': ' + message;
}
});
// when subclassing, specify the class you want to inherit from
var Pirate = Class.create(Person, { //第一個參數是class,作為超類在定義類時直接繼承
// redefine the speak method
say: function($super, message) {
return $super(message) + ', yarr!';
}
});
var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"
//聲明子類時對子類的initialize進行重寫
1.60以前
Java代碼
1. var Animal = Class.create();
2. Animal.prototype = {
3. initialize: function(name, sound) { //超類,頂一個兩個參數
4. this.name = name;
5. this.sound = sound;
6. },
7.
8. speak: function() {
9. alert(name + " says: " + sound + "!");
10. }
11. };
12.
13. var snake = new Animal("Ringneck", "hissssssssss");
14. snake.speak();
15. // -> alerts "Ringneck says: hissssssssss!"
16.
17. var Dog = Class.create();
18.
19. Dog.prototype = Object.extend(new Animal(), {
20. initialize: function(name) { //子類,定義一個參數
21. this.name = name;
22. this.sound = "woof";
23. }
24. });
25.
26. var fido = new Dog("Fido");
27. fido.speak();
28. // -> alerts "Fido says: woof!"
var Animal = Class.create();
Animal.prototype = {
initialize: function(name, sound) { //超類,頂一個兩個參數
this.name = name;
this.sound = sound;
},
speak: function() {
alert(name + " says: " + sound + "!");
}
};
var snake = new Animal("Ringneck", "hissssssssss");
snake.speak();
// -> alerts "Ringneck says: hissssssssss!"
var Dog = Class.create();
Dog.prototype = Object.extend(new Animal(), {
initialize: function(name) { //子類,定義一個參數
this.name = name;
this.sound = "woof";
}
});
var fido = new Dog("Fido");
fido.speak();
// -> alerts "Fido says: woof!"
1.60以後
Java代碼
1. var Animal = Class.create({
2. initialize: function(name, sound) {
3. this.name = name;
4. this.sound = sound;
5. },
6.
7.
8. speak: function() {
9. alert(this.name + " says: " + this.sound + "!");
10. }
11. });
12. // subclassing Animal
13. var Snake = Class.create(Animal, {
14. initialize: function($super, name) { //通過$super的方式調用超類的initliaze,
15. $super(name, 'hissssssssss');
16. }
17. });
18. var ringneck = new Snake("Ringneck");
19. ringneck.speak();
20. //-> alerts "Ringneck says: hissssssssss!"
21.
22. var rattlesnake = new Snake("Rattler");
23. rattlesnake.speak();
24. //-> alerts "Rattler says: hissssssssss!"
25.
26. // mixing-in Enumerable
27. var AnimalPen = Class.create(Enumerable, {
28. initialize: function() {
29. var args = $A(arguments);
30. if (!args.all( function(arg) { return arg instanceof Animal }))
31. throw "Only animals in here!"
32. this.animals = args;
33. },
34.
35. // implement _each to use Enumerable methods
36. _each: function(iterator) {
37. return this.animals._each(iterator);
38. }
39. });
40. var snakePen = new AnimalPen(ringneck, rattlesnake);
41. snakePen.invoke('speak');
42. //-> alerts "Ringneck says: hissssssssss!"
43. //-> alerts "Rattler says: hissssssssss!"
var Animal = Class.create({
initialize: function(name, sound) {
this.name = name;
this.sound = sound;
},
speak: function() {
alert(this.name + " says: " + this.sound + "!");
}
});
// subclassing Animal
var Snake = Class.create(Animal, {
initialize: function($super, name) { //通過$super的方式調用超類的initliaze,
$super(name, 'hissssssssss');
}
});
var ringneck = new Snake("Ringneck");
ringneck.speak();
//-> alerts "Ringneck says: hissssssssss!"
var rattlesnake = new Snake("Rattler");
rattlesnake.speak();
//-> alerts "Rattler says: hissssssssss!"
// mixing-in Enumerable
var AnimalPen = Class.create(Enumerable, {
initialize: function() {
var args = $A(arguments);
if (!args.all( function(arg) { return arg instanceof Animal }))
throw "Only animals in here!"
this.animals = args;
},
// implement _each to use Enumerable methods
_each: function(iterator) {
return this.animals._each(iterator);
}
});
var snakePen = new AnimalPen(ringneck, rattlesnake);
snakePen.invoke('speak');
//-> alerts "Ringneck says: hissssssssss!"
//-> alerts "Rattler says: hissssssssss!"