2012-04-24 44 views
3

假設我有一個繼承鏈,每個類通過添加一個新字段來擴展它的超類,並且我希望該鏈的每個類都覆蓋toString()方法,如下所示:強制繼承鏈的每一類重寫一個抽象方法

public String toString() 
{ 
    return super.toString() + "[newfield=" + newfield + "]"; 
} 

如果我使用抽象基類,那麼當通過實現抽象方法使繼承鏈的類變爲具體時,從那一點開始,所有子類都通過繼承已經實現的方法變得具體。

是否有Java的辦法迫使類重寫(重新實現),即使它已經在繼承鏈中實現更高的抽象方法?

回答

3

簡答題:沒有。

長答案:您可以編寫一個掃描類路徑的單元測試(使用類似reflections的庫),加載抽象類的每個子類並使用反射檢查該方法。但在編譯時無法做到這一點。

從Java

除此之外, AspectJhasMethod()切入點,它可以爲你做檢查,但不幸的是這僅適用於declare parents建議。也許你可以使用aspectj分兩步完成:

  • 定義了一個接口IllBehaved
  • 定義該接口分配給該從你的基類延伸,但沒有成員類的建議
  • 然後聲明爲實現此接口的所有類型的編譯錯誤

    pointcut isSubTypeOfYourClass(): within(com.your.BaseClass+); 
    pointcut overridesMethod(): hasmethod(public void yourMethodName(..)); 
    declare parents: isSubTypeOfYourClass() && !overridesMethod() 
           implements com.yourcompany.IllBehaved; 
    declare error: isSubTypeOfYourClass() && within(com.yourcompany.IllBehaved+): 
           "Implementation class must override <Foo> method"; 
    

我沒有測試過這個,但是如果你打開-XhasMember選項,它應該可以工作。 當你使用像Maven,Ant,Eclipse等標準工具時,很容易將aspectj集成到你的構建中。

+0

你可以在編譯時使用註釋和自定義註釋處理器(如果你認爲APT是編譯時,時間)。 – 2012-04-24 13:12:01

+0

@EliAcherkan真實,好點。但是我想你只能在所有重寫類都有註釋的情況下才能這樣做,對吧?或者,也許用'@ Inherited'標記的註釋可以完成這項工作? – 2012-04-24 13:18:52

+0

好問題,我承認我沒有完全想到它。我希望用註解來標記最上面的類是足夠的,並且APT允許你a)找到給定類的後代列表;或b)在所有類上調用您的註釋處理器(以便您可以檢查當前類的祖先是否有特定的註釋)。 – 2012-04-24 13:27:19

2

不,但你可以讓你的類實現一個接口,而不是抽象的超類。你可以在編譯時檢查類是否實現了接口,這取決於你對這個類做了什麼。