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

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

什么是菱形缺陷?

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

1
2
3
d = new D()
// 这里的 test 是哪个父类的方法?
d.test()

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

类 A、B、C、D 的继承关系

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

避而远之 —— 使用接口

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

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

用 PHP 举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 中运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 就复杂很多。

在此对 MRO 不多做赘述,感兴趣的同学可以移步阅读:

参考资料与扩展阅读