作者adrianshum (Alien)
看板java
标题Re: [问题] 面试时被问到介面功能
时间Fri Oct 18 06:02:50 2013
※ 引述《Killercat (杀人猫™)》之铭言:
: 为什麽物件导向语言大多数都会禁止多重继承?以及为什麽C++不算真正的OO语言?
: 其实有一部分的原因(不是全部)都跟一个关键字有关:钻石型继承
: 简单的说就是
: A
: B C
: D
: B继承A C继承A D继承於B以及C,这种东西称为钻石继承
: 乍看之下没有什麽问题,但是我们举个很简单的例子来看,马上就知道问题出在哪
: A = java的Object,B C都是java bean 所以当然理所当然的继承了Object
: A有一个原生的实作叫做Object.toString() BC都overload了toString
: 那要是有多重继承的话 D.toString会是什麽?
补充一下钻石继承。
钻石继承的问题不在於 Object.toString() 被 B/C 都 override
(我想你写 overload 是笔误?)而产生 ambiguity。这方面与有
两个 superclass 而两者有一样 signature 的 method 的问题无异。
其实刚巧我在 C/C++ 版有答过相关的问题:
#19kSHvJ- 。
Diamond inheritence 出的问题在於 D 里有多於一份的 A
所谓 inheritence, 在大部份 language 里其实都是以“包含 super
class 的 instance" 来达成。比如 B extends A,其实可以想像成
B 里面有一份 A:
+---------+
| B |
| +-----+ |
| | A | |
| +-----| |
+ --------+
你提的例子,在没有适当处理下,会变成:
+---------------------+
| D |
| +-------+ +-------+ |
| | B | | C | |
| | +---+ | | +---+ | |
| | | A | | | | A | | |
| | +---+ | | +---+ | |
| +-------+ +-------+ |
+---------------------+
这会有什麽问题?比如说:
class A{
int counter = 0;
int increment() { return ++counter; }
}
class B extends A {
void foo() { println("increment result " + increment()); }
}
class C extends A {
void bar() { println("increment result " + increment()); }
}
class D extends B, C { }
假如我有
D d;
d.foo();
d.bar();
出乎意料以外,foo() bar() 都会印出 1:虽然里面都跑了 A::increment()。
问题出在上面提到的:其实 B & C 都自带了独立的 A,所以 B/C 跑 increment
的话,其实是在 increment 不同的 A
所谓 virtual inheritence 就是把 两份 A 变为一份:
+---------------------+
| D |
| +-------+ +-------+ |
| | B | | C | |
| +-------+ +-------+ |
| ↘ ↙ |
| +---+ |
| | A | |
| +---+ |
+---------------------+
那麽不论我经 B 或 C 而acess 到的 A 都是同一份。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 223.19.45.228
1F:→ lovdkkkk:(y) 10/18 08:35
2F:推 swpoker:可以在多点吗? 10/18 09:05
3F:推 Killercat:推 这点的确是我没写好 XD 10/18 10:30
4F:推 kspacey:推 10/18 12:00
5F:→ swpoker:其实我还是觉得"继承"还是要小心使用的好 10/18 12:02
6F:推 KeySabre:推 10/18 13:14
7F:推 Killercat:主流的说法 就是多用包含少用继承 10/18 14:36
8F:推 eieio:开眼界了! 10/19 15:21
9F:推 Elohim123:推 10/25 00:40