作者Killercat (杀人猫™)
看板java
标题Re: [问题] 面试时被问到介面功能
时间Thu Oct 17 19:09:28 2013
※ 引述《swpoker (swpoker)》之铭言:
: ※ 引述《PsMonkey (痞子军团团长)》之铭言:
: 介面存在的目的就是跟推文大大说的一样
: 因为C的多重继承直接导致不可思议的问题
: 也因为本身语言的机制导致无法从语言本身解决
: 例如
: A{methodA,methodC}
: B{methodB,methodC}
: XXX 继承A,B
: 那麽methodC是???
其实这边有个很有趣的地方,可以给大家参考一下。
这种东西在C++里面会直接编译器给你打X
你一定至少得能用Koenig lookup能解析出来的形式才会让你编过去
所以其实这不是问题,语言帮你解决了:就是直接不给过
给个sample code大家去玩玩看
#include <stdio.h>
class A {
public:
void print_1() { printf("This is _1!"); };
void print_2() { printf("This is _2!"); };
};
class B {
public:
void print_1() { printf("This is _1_B!"); };
void print_3() { printf("This is _3_B!"); };
};
class C : public A, public B {
};
using namespace std;
int main(int argc, char *argv[]) {
C* c = new C();
c->print_1();
}
这样,我想编译是不会过的。除非我们很明确的指定出来
c->A::print_1();
c->B::print_1();
但是这问题还是有的,如果我们用这种方法产生呢?
A* c = new C();
c->print_1();
或者
B* c = new C();
c->print_1();
嘿嘿,这样就符合Koenig Lookup 可以找出来了,而且不会ambigious
有兴趣可以自己拿编译器玩玩看
所以其实除非使用者自己混淆自己,比方说最後两个例子。
不然其实C++设计上是有防范这些东西的。
C++讲太多不好,这里是java板。谈谈跟Java比较有关系的例子
为什麽物件导向语言大多数都会禁止多重继承?以及为什麽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会是什麽?
这东西就是所谓的钻石继承(Diamond Inheritance)
http://stackoverflow.com/questions/379053/diamond-inheritance-c/
钻石继承是一个严重的设计问题。在C++里面基本上都是能避就避
不过C++由於没有基础Object 所以其实不太容易真的碰到这个问题。
这就是为什麽OO语言(所有东西都会牵扯到一个基础物件Object)多半禁止多重继承
因为你只要多重继承,100%就是钻石继承。
C++之所以很多人不把他算OO语言也是因为他并没有一个基本的Object
那转了一大圈,我们终於可以回到正题了:Abstract跟Interface本质上差异在哪
Abstract其实也是一个继承於Object的class,所以他不管是什麽
至少都会有Abstract.toString(), Abstract.getClass()这类Object性质
而interface则否,它本身并没有代表(represent)任何一个Object
绝对不会有什麽Interface.toString()(除非你自己定义)这类的隐含性的东西
名称冲突方面,java自己也有一套机制去把名称冲突挡下来
(这个简单的小实验就交给有兴趣的人自己去玩玩看,其实差不多)
但是由於interface绝无钻石继承的问题,所以可以爱放几个就放几个
abstract class至少就会有继承到一个共通的object 所以会避免钻石继承下
自然就不会开放多重继承来使用。
P.S. Koenig Lookup是一个很庞大的规则,它定义了几乎所有的C++函数被查找的顺序
由於C++还有一个万恶渊薮叫做default value,所以Koenig Lookup其实很复杂
而这仅仅只是Koenig Lookup的一小部份而已。
不过他主要都是以「直觉」为出发点,就是「大多数人直觉上都会挑到这个」为主
所以其实复杂归复杂,却不会很困难。
有兴趣可以google这个名词。Java其实或多或少也是用这种方法去找的(吧?)
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 59.124.251.135
※ 编辑: Killercat 来自: 59.124.251.135 (10/17 19:18)
1F:推 dream1124:推, 有趣 10/17 20:09
2F:推 swpoker:推!钓到大尾的了!真棒!! 10/17 22:42
4F:推 popcorny:推!! 10/18 08:14
5F:推 lovdkkkk:(y) 10/18 08:18
6F:推 NullLife:推!! 10/18 09:03
7F:推 kspacey:推 10/18 11:20
8F:推 gary62107:推 10/18 11:35
9F:推 battle7:推推~高手 10/19 04:01
10F:推 pugboy:推推 10/19 22:44
11F:推 fonz:推 !! 10/20 11:58
12F:推 Elohim123:BC都overload了toString 应该指的是override? 10/25 00:36
13F:推 kipi91718:优文推 10/28 16:52
14F:推 Samuel77:有读有推 增长知识了!! 11/05 01:39