面向对象困境之 —— 菱形缺陷

2021-11-16 From 忘归 By 江五渣
<p> 我们知道 C++ 是支持 多重继承(multiple inheritance)的,即一个类可以同时从多于一个父类继承行为与特征。 p> <p>现在大多数现代编程语言对 多重继承 避而远之,例如 PHP 、Swift、Java 都是不支持 多重继承 的。因为多重继承增加了程序的复杂性和含糊性,例如容易导致菱形缺陷(Diamond Problem)。 p>

什么是菱形缺陷?

<p> 假设我们有一个基类 A,子类 B 和 C 都重写了 A 中的方法 test()。此时又有一个 D 类,同时继承了 B 和 C,那么当 D 调用 test() 时,继承的是哪个父类的方法呢? p> <p> 如果没有给出进一步的说明,编译器是无法给出答案的。 p> <p> 这个继承关系画出来就像一个菱形,所以这一问题也被称为菱形缺陷或钻石问题p>

避而远之 —— 使用接口

<p> 想要实现多重继承的功能,又想避免菱形问题?那就使用接口(Interface)吧!这是不支持多重继承的编程语言给出的方案p> <p> 使用接口,我们可以指定某个类必须实现哪些方法,但不需要接口定义这些方法的具体内容。一个类无论实现几个接口,最终调用的都只有一个实现p> <p> 用 PHP 举个栗子: p>
interface a
{
    function test();
}

interface b
{
    function test();
}

class C implements a, b {
    // 最终调用的都是这个实现
    function test() {
        echo 'c';
    }
}

迎难而上 —— 我用 Python

<p> 虽然很多现代编程语言对多重继承都避而远之,但 Python 依然是支持多重继承的。Python 对菱形问题处理得益于方法解析顺序(Method Resolution Order,MRO)。 p> <p> 上面一节中我们提到的例子若在 Python3 中运行p>
class A:
    def test(self):
        print("test A")

class B(A):
    def test(self):
        print("test B")

class C(A):
    def test(self):
        print("test C")

class D(B, C):
    pass

d = D()
d.test() # 此时输出 test B
<p> 对于只支持单继承的语言来说,MRO 一般比较简单。而对于 Python 这种支持多重继承的语言来说,MRO 就复杂很多。 p>

本文来源:忘归,转载请注明出处!

来源地址:http://jalan.space/2019/07/29/2019/oo-diamond-problem/

发表感想

© 2016 - 2022 chengxuzhixin.com All Rights Reserved.

浙ICP备2021034854号-1    浙公网安备 33011002016107号