2012-10-08 54 views
1

我有延伸UpdaterJava,可以修改抽象類層次結構中超類的方法聲明?

Updater一個抽象類UserdataUpdater有一個方法聲明

public abstract void processRow (Cluster cluster, IAppendOnlyData row); 

反正是有修改此方法的聲明中UserdataUpdater,使之更加具體,比如

public abstract void processRow (Cluster cluster, IUserData row); 

IUserData延伸IAppendOnlyData,因爲我想要的類延伸UserdataUpdater只能服用IUserData

+0

你能改寫你的最後一句話? – Zakaria

回答

13

不,你不能。這會破壞超類的契約,即:該方法接受IAppendOnlyData作爲第二個參數。

請記住,子類的實例也是其超類的實例。所以任何人都可以將子類實例引用爲其超類,並調用基方法,傳遞一個IAppendOnlyData,而不知道該實例實際上是一個子類實例。

瞭解更多關於Liskov substitution principle

做到這一點的唯一方法是使超通用:

public class Updater<T extends IAppendOnlyData> { 
    ... 
    public abstract void processRow(Cluster cluster, T row); 

} 

public class UserdataUpdater extends Updater<IUserData> { 
    @Override 
    public void processRow(Cluster cluster, IUserData row) { 
     ... 
    } 
} 
1

在派生類中不能修改的方法聲明。如果派生類方法具有完全相同的方法簽名,則只能覆蓋超類方法。您必須使用函數重載並使用您提到的新參數類型創建一個新方法processRow

0

以我的經驗,你必須使用第一個聲明,然後在執行,檢查,以確保:

row instanceof IUserData 
當然

,這是在運行時而非編譯期間檢查,但我不不知道任何其他方式。當然,您也可以將該行轉換爲IUserData類型,無論是盲目地還是在檢查其類型(以上)之後。

0

簡短的回答:第

您可以創建這樣的功能,但由於簽名不同的是,編譯器會認爲這是一個不同的功能。

如果你仔細想想,你試圖做的事情沒有意義。假設您編寫了一個將Updater作爲參數的函數,並使用不是IUserData的東西來調用processRow。在編譯時,Java無法知道該對象是通過Updater,UserdataUpdater還是Updater的其他子類傳遞的。那麼它應該允許這個電話嗎?編譯器應該做什麼?

你可以做的是在UserdataUpdater.processRow內部,包含檢查在運行時傳入的類型的代碼,並引發異常或執行一些其他類型的錯誤處理(如果它無效)。

0

假設您無法控制Updater類,則無法這樣做......您必須使用完全相同的簽名來實現該方法。然而,你可以檢查的row類型,你裏面執行,並決定任何處理是適當的:

public void processRow (Cluster cluster, IAppendOnlyData row) 
{ 
    if(row instanceof IUserData) 
    { 
     // your processing here 
    } 
    else 
    { 
     // Otherwise do whatever is appropriate. 
    } 
}