简体   繁体   English

JavaScript类覆盖方法

[英]Javascript class override method

I have this class 我有这堂课

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"
    }
}

// some of the interfaces (methods) //一些接口(方法)

  function IAttack(object){
        let attack = function(){}
        object.attack = attack;
    }
    function ITakeDamage(object){
        let takeDamage = function(){}
        object.takeDamage = takeDamage;
    }

My question is why does attack(target) and takeDamage(damage) don't override the methods inherited in the constructor. 我的问题是,为什么attack(target)takeDamage(damage)不会覆盖构造函数中继承的方法。 I know this may be asked before but I can't find it sorry. 我知道之前可能会问过这个问题,但我对此感到抱歉。

Up in the comments, @Bergi made an assumption that you might be instantiating new MyClass objects in the run time and refer to them. 在注释中,@ Bergi假定您可能正在运行时实例化新的MyClass对象并对其进行引用。 Because you try to change a method of an instance of an MyClass object, and not its prototype, all new instances of MyClass (create with "new" keyword) will still inherit original MyClass's properties. 因为您尝试更改MyClass对象实例的方法而不是其原型,所以MyClass的所有新实例(使用“ new”关键字创建)仍将继承原始MyClass的属性。

For example, consider a class Fruit 例如,考虑一个水果类

class Fruit {
  constructor() {
    this.pieces = 1;
  }

  cutIntoPieces(pieces) {
    this.pieces = pieces;
    return this;
  }
}

and a function f that takes any object and changes its property cutIntoPieces , setting it to a function that unconditionally returns null and does nothing else: 一个函数f ,它接受任何对象并更改其属性cutIntoPieces ,将其设置为一个无条件返回null cutIntoPieces执行其他任何操作的函数:

const f = object => {
  object.cutIntoPieces = () => null;
};

Let's play around with it a bit in Node REPL: 让我们在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 }

You can see that calling f on banana changed its behavior when you want to cut it into pieces. 您可以看到,将香蕉切成薄片时,在香蕉上调用f改变其行为。 This happened because now bananas has its own property cutIntoPieces , which is a function that unconditionally returns null and doesn't affect the object. 发生这种情况是因为现在香蕉具有自己的属性 cutIntoPieces ,该函数无条件返回null且不影响对象。

To redefine the method cutIntoPieces in all instances of the object, we need to change it in their prototype, which is Fruit: 要在对象的所有实例中重新定义方法cutIntoPieces ,我们需要在其原型(即Fruit)中对其进行更改:

> Object.getPrototypeOf(banana);
Fruit {}

To make such a function that takes a prototype of an object and changes a property of it, so that all instances of that object inherit the changed property, we need to remake our function f a bit. 为了使这样一个函数,它的原型对象并改变它的属性,因此该对象的所有实例继承更改属性,我们需要重新塑造我们的函数f了一下。 Let's declare another function and call it g : 让我们声明另一个函数并将其命名为g

const g = object => {
  object.cutIntoPieces = function (cuts) {
    this.pieces = 2 ** cuts;
    return this;
  };
};

Here, g redefined the method cutIntoPieces of any object to make cutting more efficient. 在此, g重新定义了任何对象的cutIntoPieces方法,以使切割效率更高。 Now, if we call g with Fruit.prototype, it will change the method cutIntoPieces of orange and papaya: 现在,如果我们用Fruit.prototype调用g ,它将更改方法orange和番木瓜的cutIntoPieces

> g(Fruit.prototype);
undefined
> orange.cutIntoPieces(4);
Fruit { pieces: 16 }
> papaya.cutIntoPieces(10);
Fruit { pieces: 1024 }

What's up with banana then? 那香蕉怎么了?

> banana.cutIntoPieces(2);
null
> banana
Fruit { pieces: 1, cutIntoPieces: [Function] }

Because we called f on banana, banana.cutIntoPieces is now not related to Fruit.prototype.cutIntoPieces . 因为我们在香蕉上调用了fbanana.cutIntoPieces现在与Fruit.prototype.cutIntoPieces不相关。 While orange and papaya have this method inherited from the prototype, banana has its own: 尽管Orange和木瓜具有从原型继承的此方法,但是香蕉有其自己的:

> orange.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> papaya.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
false

Which is fine, I guess. 我猜这很好。 In case you only want to change behavior of one instance, you can define its own property, its own method; 如果只想更改一个实例的行为,则可以定义自己的属性,自己的方法; on the other hand, when you need to change behavior of all instances that have methods inherited from prototype, you can change their prototype. 另一方面,当您需要更改所有具有从原型继承的方法的实例的行为时,可以更改其原型。

But how to get banana behave identically to other fruit when cut into pieces? 但是如何将香蕉切成薄片后表现出与其他水果相同的效果? Let's delete its own cutIntoPieces ! 让我们删除它自己的cutIntoPieces

> delete banana.cutIntoPieces
true
> banana
Fruit { pieces: 1 }
> banana.cutIntoPieces(2)
Fruit { pieces: 4 }

See, after you remove object's own property, another one, with the same name, is inherited from the prototype, when there is one: 请参阅,在删除对象自己的属性后,如果有一个,则从原型继承另一个同名的属性:

> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
true

Now banana, orange and papaya behave identically. 现在,香蕉,橙和木瓜的行为相同。

Hope it helps and best of luck! 希望对您有帮助,并祝您好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM