ES6 Classes执行多态的能力

Bio*_*ika 5 javascript polymorphism ecmascript-6

我试图通过ES6类来模拟多态性,以便能够更好地理解这个理论.

概念很明确(设计对象以共享行为并能够覆盖特定行为的共享行为)但我担心上面的代码不是有效的多态性示例.

由于我缺乏经验,如果您以全面的方式回答这些问题,我将不胜感激:

  • 事实上,两个类都有一个同名的方法,并且每个类的实例都能正确访问它们各自的方法,这使得这个多态的例子?
  • 如果这不能模仿polimorphism,那么应该在代码中做些什么改变呢?
  • 我已经尝试删除该Employee.prototype = new Person();行,它仍然有效.这就是为什么我担心我没有得到这个概念.

class Person {
        constructor (name, age) {
          this._name = name;
          this._age = age;
        }
      }

      Person.prototype.showInfo = function(){
        return "Im " + this._name + ", aged " + this._age;
      };


      class Employee {
        constructor (name, age, sex) {
          this._name = name;
          this._age = age;
          this._sex = sex;
        }
      }

      Employee.prototype = new Person();

      Employee.prototype.showInfo = function(){
        return "Im " + this._sex + ", named " + this._name + ", aged " + this._age;
      };


      var myPerson = new Person('Jon', 20);
      var myEmployee = new Employee('Doe', 10, 'men');

      document.write(myPerson.showInfo() + "<br><br>");   // Im Jon, aged 20
      document.write(myEmployee.showInfo() + "<br><br>"); // Im men, named Doe, aged 10
Run Code Online (Sandbox Code Playgroud)

geo*_*geo 12

每个JavaScript对象都有一个内部的"prototype"属性,通常称为[[prototype]],它指向它直接继承的对象.

每个JavaScript函数[object]都有一个属性原型,用一个[几乎]空对象初始化.当您通过将其作为构造函数调用来创建此函数的新实例时,该新对象的[[prototype]]将指向构造函数的原型对象.

所以,当你写这个时var myPerson = new Person('Jon', 20);,你有方法showInfo,因为你有这个

Person.prototype.showInfo = function(){
    return "Im " + this._name + ", aged " + this._age;
};
Run Code Online (Sandbox Code Playgroud)

使用ES6,如果你想看到多态,你可以这样做:

class Person {
    constructor (name, age) {
        this._name = name;
        this._age = age;
    }
        
    showInfo () {
        return "Im " + this._name + ", aged " + this._age;
    }
}

class Employee extends Person {
    constructor (name, age, sex) {
        super(name,age);
        this._sex = sex;
    }
        
    showInfo(){
        return "Im " + this._sex + ", named " + this._name + ", aged " + this._age;
    }
}

var myPerson = new Person('Jon', 20);
var myEmployee = new Employee('Doe', 10, 'men');

document.write(myPerson.showInfo() + "<br><br>");   // Im Jon, aged 20
document.write(myEmployee.showInfo() + "<br><br>"); // Im men, named Doe, aged 10
Run Code Online (Sandbox Code Playgroud)


min*_*gos 5

您正在混合 ES5 和 ES6。此外,您只是创建了两个类。Employee并没有真正继承自Person. 你想要的代码应该是这样的:

class Person {
    constructor(name, age) {
        this._name = name;
        this._age = age;
    }

    showInfo() {
        return `I'm ${this._name}, aged ${this._age}.`;
    }
}

class Employee extends Person {
    constructor(name, age, sex) {
        super(name, age);
        this._sex = sex;
    }

    showInfo() {
        return `I'm a ${this._sex} named ${this._name}, aged ${this._age}.`;
    }
}

const alice = new Person("Alice", 20);
const bob = new Employee("Bob", 25, "male");

console.log(alice.showInfo());
console.log(bob.showInfo());
Run Code Online (Sandbox Code Playgroud)

因此,这里是对更改内容的快速回顾。

首先,不需要再分配 aprototype了。相反,您可以extend在父类中创建子类。您可以使用super()子构造函数中的调用来调用父构造函数 - 这将设置由父构造函数处理的属性。请注意,我们不再在子 ctor 中设置nameage!这就是为什么您的示例在删除设置子原型的行后仍然有效的原因:您无论如何都要手动设置属性。

方法在类内部定义;无需使用prototype. 您只需在子类中声明它就可以覆盖它。

如果您需要任何其他说明,请在评论中提问。