在之前的代码中就有两个这样的例子:drive() 被定义在 Vehicle 和 Car 中 , ignition() 被定义在 Vehicle 和 SpeedBoat 中 。
我们可以在 ignition 中看到多态非常有趣的一点 。 在 pilot 中通过相对多态引用了 Vehicle 中的 drive 。 但是那个 drive 方法直接通过名字引用了 ignition 方法 。
作者在这里介绍的是传统语言中的多态 。 这里讲了太多的例子 , 看起来有些混乱 。
那么语言引擎会使用哪个 ignition 呢?Vehicle 还是 SpeedBoat 的?实际上它会使用 SpeedBoat 的 ignition 。 如果你直接实例化了 Vehicle 类然后调用它的 drive , 那语言引擎就会使用 Vehicle 中的 ignition 方法 。
换言之 , ignition 方法中的定义的多态性取决于你是在哪个类的实例中引用它 。
这似乎是一个过于深入的学术细节 , 但是只有深入了解这个细节才能理解 JavaScript 中的类似的 [[Prototype
机制 。
在子类中也可以相对引用它继承的父类 , 这种相对引用通常被称为 super 。
注意这些实例(a1a2b1b2)和继承(Bar)箭头表示复制操作 。
从概念上来说 , 子类 Bar 应当可以通过相对多态引用(或者说 super)来访问父类 Foo 中的行为 。 需要注意的是 , 子类得到的仅仅是继承自父类行为的一个副本 。 子类对继承到的一个方法进行重写 , 不会影响到父类的方法 , 这两个方法之间互不影响 , 因此才能使用相对多态访问父类中的方法 。
多态并不表示子类和父类有关联 , 子类得到的只是父类的一个副本 , 类的继承其实就是复制 。
多重继承还记得我们之前关于父类、子类的 DNA 讨论吗?当时我们说这个比喻不太恰当 , 因为现实中绝大多数是由双亲生的 。 如果类可以继承两个类 , 那看起来就更符合现实了 。
作者在这里对多态进行了案例的介绍 , 观点只有一个:类的继承其实就是复制 , 子类是一个副本 。
有些面向对象的类允许你继承多个「父类」 。 多重继承意味着所有的父类的定义都会被复制到子类中 。
从表面来看 , 对于类来说这似乎是一个非常有用的功能 , 可以把多个功能组合到一起 , 然而 , 这个机制同时也会带来复杂的问题 。 如果两个父类都定义了 drive 方法的话 , 那么子类引用的是哪一个呢?难道每次都需要手动指定具体父类的 drive 方法吗?
除此之外 , 还有一种被称为钻石问题的变种 。 在钻石问题中 , 子类 D 继承两个父类 B 和 C , 这两个父类都继承自 A 。 如果 A 中有 drive 方法 , 并且 B 和 C 都重写了这个方法的 , 那么 D 引用 drive 时应该选择哪个版本呢?
这些问题远比看上去复杂得多 , 之所以要介绍这些问题 , 主要是为了和 JavaScript 的机制进行对比 。
相比之下 , JavaScript 要简单的多:它本身并不提供「多重继承」功能 。 许多人认为这是件好事 , 因为使用多重继承的代价太高 。 然而这无法阻挡开发者们的热情 , 他们会尝试各种办法来实现多重继承 。
混入在继承或者实例化时 , JavaScript 的对象机制并不会自动执行复制行为 。 简单来说 , JavaScript 中只有对象 , 并不存在可以被实例化的「类」 。 一个对象并不会被复制到其他对象 , 它们会关联起来 。
由于在其他语言中类表现出来的都是复制行为 , 因此 JavaScript 开发者想出一个方法来模拟类的复制行为 , 这个方法就是混入 。 接下来我们会看到两种类型的混入:显式和隐式 。
- 尽管大刀阔斧地尝鲜了大小核混合架构|13代酷睿最大睿频比12900ks还要高200~300mhz
- 【竞彩课堂】什么是单场投注?什么是混合过关?
- 科大讯飞|10.1英寸护眼大屏!科大讯飞AI学习机A10图赏
- 苹果9英寸折叠屏曝光!加持ToDesk后堪称iPhone/iPad/Mac混合体
- 京东云混合多云操作系统云舰,解决企业出海运维难题
- 10.89万元起,风行T5 EVO热浪联名伍六七高燃上市
- javascript|微信新功能:暴露了谁最爱你
- javascript|玩家利用3D打印技术制作了《宝可梦》中的小火龙,还带它出门露营
- 游戏性能稳了!联想小新Pro 16 2022显卡曝光:RTX3050 Ti支持混合输出
- RTX|联想小新Pro 16 2022显卡曝光:RTX3050 Ti 支持混合输出