2011-09-07 77 views
5

java中的覆蓋方法具有以下功能:java中的覆蓋方法約束

1> Overrinding方法應該具有與Parent類方法相同的參數列表。

2>返回類型應該與父類方法的返回類型相同/子類。

3>訪問級別應與父類方法相同或更少限制。

4>重寫方法可以拋出相同或更窄的異常,而不是更廣泛的。

* 只是想知道爲什麼會這樣的點*

* 2 - 爲什麼子爲什麼不超? *

3 - 爲什麼訪問級別應該限制較少?

4 - 爲什麼它應該拋出狹窄的異常?

按我的理解它只是如果我創建一個父類refrence創建一個子類對象,並試圖跑下來每個場景,然後

讓我們假設A是父類B是子類均具有方法printAndReturnSomething()

public class A{ 

     public B printAndReturnSomething(){ 
       S.O.P("Inside A Print"); 
       return new B(); 
       } 
} 

現在我們有孩子的B類爲

public class B extends A{ 
     public A printAndReturnSomething(){ // I know this isn't possible to return A but had it been then 
       S.O.P("Inside A Print"); 
       return new A(); 
       } 
} 

現在,如果我做這樣的事情

A a =new B(); 

,現在我有一個這樣的引用我期待的返回類型爲B型的

B returnedValue=a.printAndReturnSomething(); // But it actually calls the child class method and hence returns A. So here comes the contradiction. 

Similaraly爲情景3和4.我的理解是否正確?我錯過了其他更相關的東西嗎?

回答

5

所有這一切都可以歸納爲「一個子類必須表現得好像它是一個超類」。因此,如果Derived延伸了Base並且我有Derived類型的對象x,那麼我希望它的行爲與Base類型完全相同。

所以如果x.foo()返回某種類型的T,並且Base::foo()返回類型S,那麼我希望能夠治療x.foo()S,所以T最好是相同或S一個子類。

同樣,x.foo()應該只會拋出Base:foo()承諾的例外情況。它無法開始拋出新的意外的例外。

如果Base::foo()是公開的,那麼x.foo()應該如此。你不能突然對派生類有更嚴格的限制,因爲基類向我保證它是公開的。

總是將繼承看作「行爲像超類」,或者「可以像超類一樣對待」,所有這些都應該清楚。

+0

感謝您的回答,特別是最後一行「始終將繼承看作」像超類一樣行事「,或者」可以像超類一樣對待「,所有這些都應該清楚。 – Deva

3

點#2

想象以下:

class Animal {} 
class Dog extends Animal {} 

class Base { 
    Dog get() { ... } 
} 

class Derived extends Base { 
    Animal get() { ... } 
} 

Base b = new Derived(); 
Dog d = b.get(); // What? 

類似的邏輯可被施加到其他的問題。

+0

感謝您的回覆。這個問題我已經提到過了。我想檢查的是這是唯一的原因? – Deva

+2

@Deva:這是一個非常重要的原因!它根本沒有任何意義。 –

+0

Yup Thanks Oli .. – Deva

1

要回答你兩點:

2 - 爲什麼子爲什麼不超?

若父類被允許,這可能發生:

class A { 
    public A makeCopy() { return clone(); } 
} 

class B extends A { 
    public Object makeCopy() { return new Date(); } 
} 

public static void main(String[] args) { 
    A a = new B(); 
    A copy = a.makeCopy(); // OOPS -- didn't get an A after all! 
} 

3 - 爲什麼訪問級別應該是限制較少?

修改上面的B類:

class B extends A { 
    private A makeCopy() { return clone(); } 
} 

public static void main(String[] args) { 
    A a = new B(); 
    A copy = a.makeCopy(); // OOPS -- accessing a private method! 
} 

4 - 爲什麼要拋出異常狹窄?

同樣的想法 - 如果A.makeCopy宣佈拋出AException(假設的例外A聲明的類),但B.makeCopy被宣佈扔Throwable,然後B.makeCopy可以扔任何東西。這將使得在main中不可能合理地編寫try/catch塊。

4

按我的理解它只是如果我創建一個父類refrence創建一個子類對象,並試圖跑下來每個場景......

我想你groked正確的想法。

案例與父類引用子類對象是哪裏所謂Liskov substitution principle發揮作用:在計算機程序中,如果S是T的子類型,那麼類型T的對象[這是你的「父類」] 可以用類型S [也就是你的「子類對象」] (即,類型S的對象可以替代類型T的對象)的對象替換,而不改變該程序的任何期望屬性(正確性,任務演出等)...

+1

+1提里斯科夫替代原則 – Andrey