[英]Javascript class override method
我有這堂課
class MyClass {
constructor(name, health, damage){
INamable(this)
IHealth(this)
IDamage(this)
IAttack(this)
ITakeDamage(this)
this.setName(name)
this.setHealth(health)
this.setDamage(damage)
}
attack(target){
target.takeDamage(this.getDamage());
}
takeDamage(damage){
this.setHealth(this.getHealth() - damage);
if(this.getHealth()<=0){
this.die();
}
}
toString(){
return "myClassToString"
}
}
//一些接口(方法)
function IAttack(object){
let attack = function(){}
object.attack = attack;
}
function ITakeDamage(object){
let takeDamage = function(){}
object.takeDamage = takeDamage;
}
我的問題是,為什么attack(target)
和takeDamage(damage)
不會覆蓋構造函數中繼承的方法。 我知道之前可能會問過這個問題,但我對此感到抱歉。
在注釋中,@ Bergi假定您可能正在運行時實例化新的MyClass對象並對其進行引用。 因為您嘗試更改MyClass對象實例的方法而不是其原型,所以MyClass的所有新實例(使用“ new”關鍵字創建)仍將繼承原始MyClass的屬性。
例如,考慮一個水果類
class Fruit {
constructor() {
this.pieces = 1;
}
cutIntoPieces(pieces) {
this.pieces = pieces;
return this;
}
}
一個函數f
,它接受任何對象並更改其屬性cutIntoPieces
,將其設置為一個無條件返回null cutIntoPieces
執行其他任何操作的函數:
const f = object => {
object.cutIntoPieces = () => null;
};
讓我們在Node REPL中嘗試一下:
> banana = new Fruit();
Fruit { pieces: 1 }
> orange = new Fruit();
Fruit { pieces: 1 }
> papaya = new Fruit();
Fruit { pieces: 1 }
> f(banana);
undefined
> banana.cutIntoPieces(2);
null
> banana
Fruit { pieces: 1, cutIntoPieces: [Function] }
> orange.cutIntoPieces(3);
Fruit { pieces: 3 }
> papaya.cutIntoPieces(4);
Fruit { pieces: 4 }
您可以看到,將香蕉切成薄片時,在香蕉上調用f
改變其行為。 發生這種情況是因為現在香蕉具有自己的屬性 cutIntoPieces
,該函數無條件返回null且不影響對象。
要在對象的所有實例中重新定義方法cutIntoPieces
,我們需要在其原型(即Fruit)中對其進行更改:
> Object.getPrototypeOf(banana);
Fruit {}
為了使這樣一個函數,它的原型對象並改變它的屬性,因此該對象的所有實例繼承更改屬性,我們需要重新塑造我們的函數f
了一下。 讓我們聲明另一個函數並將其命名為g
:
const g = object => {
object.cutIntoPieces = function (cuts) {
this.pieces = 2 ** cuts;
return this;
};
};
在此, g
重新定義了任何對象的cutIntoPieces
方法,以使切割效率更高。 現在,如果我們用Fruit.prototype調用g
,它將更改方法orange和番木瓜的cutIntoPieces
:
> g(Fruit.prototype);
undefined
> orange.cutIntoPieces(4);
Fruit { pieces: 16 }
> papaya.cutIntoPieces(10);
Fruit { pieces: 1024 }
那香蕉怎么了?
> banana.cutIntoPieces(2);
null
> banana
Fruit { pieces: 1, cutIntoPieces: [Function] }
因為我們在香蕉上調用了f
, banana.cutIntoPieces
現在與Fruit.prototype.cutIntoPieces
不相關。 盡管Orange和木瓜具有從原型繼承的此方法,但是香蕉有其自己的:
> orange.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> papaya.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
false
我猜這很好。 如果只想更改一個實例的行為,則可以定義自己的屬性,自己的方法; 另一方面,當您需要更改所有具有從原型繼承的方法的實例的行為時,可以更改其原型。
但是如何將香蕉切成薄片后表現出與其他水果相同的效果? 讓我們刪除它自己的cutIntoPieces
!
> delete banana.cutIntoPieces
true
> banana
Fruit { pieces: 1 }
> banana.cutIntoPieces(2)
Fruit { pieces: 4 }
請參閱,在刪除對象自己的屬性后,如果有一個,則從原型繼承另一個同名的屬性:
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
現在,香蕉,橙和木瓜的行為相同。
希望對您有幫助,並祝您好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.