javascript - Javascript类覆盖方法
问题描述
我有这门课
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 的属性。
例如,考虑一个类 Fruit
class Fruit {
constructor() {
this.pieces = 1;
}
cutIntoPieces(pieces) {
this.pieces = pieces;
return this;
}
}
以及一个f
接受任何对象并更改其属性的函数,将其cutIntoPieces
设置为无条件返回 null 且不执行任何其他操作的函数:
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
,让切割更高效。现在,如果我们g
用 Fruit.prototype 调用,它会改变cutIntoPieces
orange 和 papaya 的方法:
> 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,banana.cutIntoPieces
现在已经不相关了Fruit.prototype.cutIntoPieces
。虽然 orange 和 papaya 继承了原型的这个方法,banana 有自己的:
> 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
现在香蕉、橙子和木瓜的行为相同。
希望它有所帮助,祝你好运!
推荐阅读
- tensorflow - 我正在尝试使用 keras 中的 to_categorical 方法将我的变量转换为分类变量并面临问题
- python - 我想将存储在示波器中的图像文件传输到电脑上,并在电脑上用Python读取
- java - 饼图值未在悬停时显示
- sql - LEFT 和 RIGHT 中的所有行都放在一个堆栈中
- javascript - 如何在javascript html中为父/子添加节点
- spring - Spring OAuth2 - 如何一起使用授权类型`password`和`client_credentials`但过期时间不同
- python - 有没有办法使用 python 向文件添加属性/元数据?
- javascript - 有向无环图的平面计算
- r - 将预测结果保存在 R 中的 csv 文件中
- reactjs - PureComponent 中的受控输入不会在更改时呈现