你不知道的JS系列上( 44 ) - 多态

class Vehicle {
  constructor() {
    this.engines = 1
  }

  ignition () {
    console.log('Turning on my engine');
  }

  drive () {
    this.ignition();
    console.log('Steering and moving forward!')
  }
}

class Car extends Vehicle {
  constructor() {
    super()
    this.wheels = 4
  }

  drive () {
    super.drive()
    console.log('Rolling on all ', this.wheels, ' wheels')
  }
}

class SpeedBoat extends Vehicle {
  constructor() {
    super();
    this.engines = 2
  }

  ignition () {
    console.log('Turning on my ', this.engines, ' engines.');
  }

  pilot() {
    super.drive()
    console.log('Speeding through the water with ease!')
  }
}

Car 重写了继承自父类的 drive() 方法,但是之后 Car 调用了 super.drive() 方法,这表明 Car 可以引用继承来的原始 drive() 方法。快艇的 pilot() 方法同样引用了原始 drive() 方法

 

这个技术被称为多态或者虚拟多态。在本例中,更恰当的说法是相对多态。之所以说 “相对” 是因为我们并不会定义想要访问的类,而是相对引用 “查找上一层”。在子类中也可以相对引用它继承的父类,这种相对引用通常被称为 super。

 

多态的另一方面是,在继承链的不同层次中一个方法名可以被多次定义,当调用方法时会自动选择合适的定义

 

在 pilot() 中通过相对多态引用了父类的 drive(),但是那个 drive() 方法直接通过名字引用了 ignition() 方法。那么语言引擎使用那个 ignition()呢,父类的还是子类的? 实际上会使用子类的,如果你是直接实例化父类,那语言引擎就会使用父类的 ignition() 方法。

 

换言之,ignition() 方法定义的多态性取决于你是在哪个类的实例中引用它

 

子类得到的仅仅是继承自父类行为的一个副本。子类对继承到的一个方法进行重写,不会影响父类中的方法,这两个方法互不影响,因此才能使用相对多态引用访问父类的方法(如果重写会影响父类的方法,那重写之后父类中的原始方法就不存在了,自然无法引用)

 

多态不表示子类和父类有关联,子类得到只是父类的一份副本,类的继承其实就是复制
posted @ 2020-04-05 10:20  wzndkj  阅读(203)  评论(0编辑  收藏  举报