Java面試題:多繼承
英文原文:Codemonkeyism,編譯:劉志軍
招聘和面試對開發(fā)經(jīng)理來說是一個無盡頭的工作,雖然有時你可以從HR這邊獲得一些幫助,但是最后還是得由你來拍板,或者就像另一篇文章“Java 面試題:寫一個字符串的反轉(zhuǎn)”所說:
面試開發(fā)人員不僅辛苦而且乏味,當然也有一些極好的參考,如:Joel Guerilla Guide to interviewing,但是最后錄用與否你來決定。為了快速了解他們的編程能力,我已經(jīng)想好要問他們字符串反轉(zhuǎn)的問題。
除了字符串反轉(zhuǎn)的問題外,還有一道好題。
Java是否支持多重繼承?
好了,很明顯傳統(tǒng)意義上Java并沒有多繼承,所以正確的答案應(yīng)該是:“沒有”或者“有,但是”或者“沒有,但是”。單從這點就可以探索出不同的方法來。通常我會問“是否因Java語言的設(shè)計者笨到?jīng)]法實現(xiàn)多重繼承”作為我們話題的開始,為什么C++那幫家伙實現(xiàn)了呢?我主要以菱形繼承問題來說明:
在面向?qū)ο蟮木幊陶Z言中總伴隨著多重繼承及組織的理解。菱形繼承問題就是在如下情景時出現(xiàn)含糊不清的情況:當兩個類B和C繼承自A,類D同時繼承自B和C, 如果D中的一個方法調(diào)用一個在A中定義的方法(不是覆蓋方法).而B和C分別用不同地方式重寫(overridden)了方法,那么這個方法到底是繼承的哪個類呢,B還是C?
另一探索性的方法是:Java怎么模擬“多重繼承”?我想答案已經(jīng)浮出水面了,就是接口(Interface)。我們經(jīng)常在Java中討論接口,那么應(yīng)試者在什么時候,怎么使用接口的呢? 使用接口又有什么好處呢?應(yīng)試者是否喜歡使用接口?我可以檢測他對建模有多熟練,有時還會讓他針對接口畫畫圖。我們繼續(xù)談?wù)揓ava中接口的問題,當兩個 接口有相同的靜態(tài)域(field),有一個類實現(xiàn)了Java中所謂的“多繼承”的兩個接口時會出現(xiàn)什么情況?
- publicinterfaceI1 {
- String NAME = "codemonkeyism";
- }
- publicinterfaceI2 {
- String NAME = "stephan";
- }
- publicclassC implementsI1, I2 {
- publicstaticvoidmain(String[] args) {
- System.out.println(NAME);
C.java:3: reference to NAME is ambiguous, both variable NAME in I1 and variable NAME in I2 match System.out.println(NAME); ^ 1 error
還有更多的方法和我們的應(yīng)試者去探討多繼承的問題, 例如:接口中方法的修飾符是什么?對于菱形繼承問題使用traits實現(xiàn)混合結(jié)構(gòu)是否比使用接口更好,還是和多繼承一樣的糟糕?正如我不在那么鐘愛繼承一 樣,大量使用繼承是一種代碼異味。我們還可以和應(yīng)試者討論繼承的負面因素—–重耦合的例子。
為什么會有這問題?
我為什么會問這個問題呢,從這個問題中又學到了什么?繼承在面向?qū)ο螅∣O)中是很基礎(chǔ)的概念,是每個Java程序員都應(yīng)該理解的概念。同時也是他反映到工 作中,理解超出語法層面的另一個基本的特性。所以對于多繼承問題,我喜歡那些可以引出很多可以探討與思考的問題。這個繼承問題只是多繼承、語言設(shè)計、代碼 味道、解決方案、接口、基于角色的開發(fā)等眾多問題中的一種而已。