在您发布的示例中,method() 方法在 Teacher 和 Student 类中继承,因此它不是多态的。
如果您将 method() 添加到 Teacher 和/或 Student 子类,那么您的某些类的行为可能会略有不同,具体取决于它们是实例的类型
例如
class Person {
constructor(name) {
this.name = name
}
method() {
// I've moved the console.log (side effect) for sake of simplicity
return this.name
}
}
// no need to add constructor because is inherited from Person
// nor method, because it inherits method too
class Student extends Person {}
class Teacher extends Person {
// inherits constructor...
// override method decorating it
method() {
return super.method() + ", is a teacher"
}
}
class Employee extends Person {
static count = 0;
// override constructor necessarily decorating it
constructor(name){
super(name)
this.id = ++this.constructor.count;
}
// override method
method(){
return "employee " +this.id
}
}
Employee.count = 0
// fill a list of different types of Person
var people = [
new Student("James"),
new Teacher("Alastair"),
new Employee("Bob"),
]
// print all the instances
people.forEach(x => console.log(x.method()))
您还必须通过层次结构维护类的兼容性(相同或更广泛的参数集,相同或更明确定义的返回类型),这被称为Liskov substitution principle。
IMO JS 和 ES6 不是学习传统 OOP 原则的最佳语言,因为它们都具有基于原型的继承和弱类型系统。
在JS中很容易compose不同的行为(方法)当你创建实例,然后使用多态而不继承,一个简单的方法可以是下面的例子
class Person {
constructor({name, ...tail}){
if(!name){
throw new TypeError("person.name is missing")
}
Object.assign(this, {name, ...tail})
}
method(){
return this.name
}
greet(){ return "hi"}
}
class Robot {
constructor(...args){
Object.assign(this, ...args)
if(this.constructor.prototype !== Object.getPrototypeOf(this)) {
// throw if __proto__ pollution on the instance
throw new TypeError("override __proto__")
}
}
method(){
return `a robot that says ${
Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString("2")
}`
}
}
// the following code might seem unclear but in return
// it could be used with instances of different classes
function introduce(){
return this.greet() +
", I'm " +
this.constructor.prototype.method.apply(this, arguments)
}
// fill a list of different instances of Person
var people = [
new Person({name: "James"}),
new Person({
name: "Alastair",
method: introduce,
}),
new Person({
name: "Bob",
method: introduce,
greet: () => "hola"
}),
new Robot({
method: introduce,
greet: () => "hello"
})
]
// print all the instances
people.forEach(x => console.log(x.method()))
归根结底,多态性是指您有不同的类共享方面但不共享行为,因此它们具有具有相同名称的方法,可能具有相同的参数,可能具有相同的返回类型,但具有不同的实现,并且可以互换使用。
让我们拿枪、钻头和电动螺丝刀,它们都有相同的方面trigger,但如果你扣动扳机,它们的行为都会有所不同