为什么接口的多重继承比一组类的多重继承要容易得多?我被一个大学问题困住了。谢谢
4 回答
如果你从不同的类继承了两个具有相同签名的方法,那么在调用这个方法时就会产生歧义。它可以解决,但可以说是一个混乱的情况。
如果你用相同的方法签名实现两个接口,那没关系,因为调用方法时仍然只有一个实现可供选择。
钻石问题是上述问题的延伸,它使情况更加混乱。当将多重继承限制为接口时,这个问题基本上就消失了。
也许是因为粒度:你可以选择你的类应该实现哪些接口。而如果你扩展一个类,你会自动继承整个类的层次结构。
两个可能的原因:1.)钻石问题(在维基百科中查找),2.)对象身份。
class A { }
class B { }
class C : A, B { }
C * c = new C ();
A * a = c;
B * b = c;
然后,您无法通过简单地测试 a == b 来验证对象身份。如果您尝试在语言中实现此功能,则不能在后台使用简单的指针运算,这样每次访问类(独立于多重继承)都会变得更加昂贵,因为 a 和 b 不再是普通指针。
如果 A 和 B 是接口,您就知道问题所在(您知道它们将被继承),这样您就可以区别对待对接口的访问与对类的访问。
顺便说一句:多类继承并不难实现。
编辑:加法。它引入了概念问题:
class C0 { virtual int meth { return 0; } };
class C1 : C0 { virtual int meth { return 1; } };
class C2 : C1, C0 { }
如果我们定义
C2 * c2 = new C2;
什么应该
((C1 *) c2)->meth()
和
((C0 *) c2)->meth()
回来是为了不迷惑人?(编辑:更正了这个例子。)
至少在 .net 中指出,接口方法仅适用于声明为或约束为接口类型的对象。因此,如果 aC1
具有方法Foo
,并且还实现了接口Intf1
,并且Intf2
每个接口都声明了一个方法Foo
,那么在大多数情况下,存在三个命名的方法这一事实Foo
并不重要,因为它们将存在于本质上是独立的域中。
此外,如果一个 interfaceIDerived1
和IDerived2
inherit IBase
,其中包括 member Foo
,一个实现这两个接口的类,或者一个继承这两个接口的接口,将只定义 的一个定义IBase.Foo
。、和/或从两者派生的接口可以声明它们自己的成员IDerived1
,但任何此类定义都将与. 将派生接口转换为并调用它总是会产生相同的方法,无论是否直接转换为IDerived2
Foo
IBase.Foo
IBase
Foo
IBase.Foo
IBase
,或者先转换到其他接口。相比之下,如果一个类派生自其他两个类,而这两个类都覆盖了一个公共基类的同一个成员,那么如果将派生类的一个对象强制转换为基类然后尝试使用该成员会发生什么就不清楚了.
顺便说一句,有几种情况可能会产生歧义。如果一个接口继承了两个具有相同名称成员的接口,则可能需要使用一些技巧来强制编译器偏爱一个,或者让派生接口添加自己的同名成员,这会影响两个原件。此外,在使用泛型时,可以约束泛型类型以实现多个接口并从类继承。完成此操作后,如果接口和/或类共享成员名称,则可能会产生歧义。