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

2021-11-16 From 忘归 By 江五渣

我们知道 C++ 是支持 多重继承(multiple inheritance)的,即一个类可以同时从多于一个父类继承行为与特征。

而现在大多数现代编程语言对 多重继承 避而远之,例如 PHP 、Swift、Java 都是不支持 多重继承 的。因为多重继承增加了程序的复杂性和含糊性,例如容易导致菱形缺陷(Diamond Problem)。

什么是菱形缺陷?

假设我们有一个基类 A,子类 B 和 C 都重写了 A 中的方法 test()。此时又有一个 D 类,同时继承了 B 和 C,那么当 D 调用 test() 时,继承的是哪个父类的方法呢?

如果没有给出进一步的说明,编译器是无法给出答案的。

这个继承关系画出来就像一个菱形,所以这一问题也被称为菱形缺陷或钻石问题。

避而远之 —— 使用接口

想要实现多重继承的功能,又想避免菱形问题?那就使用接口(Interface)吧!这是不支持多重继承的编程语言给出的方案。

使用接口,我们可以指定某个类必须实现哪些方法,但不需要在接口中定义这些方法的具体内容。一个类无论实现几个接口,最终调用的都只有一个实现。

用 PHP 举个栗子:

interface a
{
    function test();
}

interface b
{
    function test();
}

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

迎难而上 —— 我用 Python

虽然很多现代编程语言对多重继承都避而远之,但 Python 依然是支持多重继承的。Python 对菱形问题的处理得益于方法解析顺序(Method Resolution Order,MRO)。

上面一节中我们提到的例子若在 Python3 中运行:

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

对于只支持单继承的语言来说,MRO 一般比较简单。而对于 Python 这种支持多重继承的语言来说,MRO 就复杂很多。

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

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

君子曰:学不可以已。
《知识图谱:概念与技术》

知识图谱是一种大规模语义网络,已经成为大数据时代知识工程的代表性进展。知识图谱技术是实现机器认知智能和推动各行业智能化发展的关键基础技术。知识图谱也成为大规模知识工程的代表性实践,其学科日益完善。本书是一本系统介绍知识图谱概念、技术与实践的书籍。

发表感想

© 2016 - 2024 chengxuzhixin.com All Rights Reserved.

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