2014-03-12 66 views
2

是否有可能爲子類中的方法定義一些默認行爲,而無需致電super?假設我們想要在超類中設置一個boolean的值,並且你想從子類中隱藏這個值,有沒有辦法隱藏修改的布爾值?假設我們有以下的基類BaseTest不使用super的子類方法的默認行爲是什麼?

public class BaseTest { 
    private boolean mIsInitialized = false; 

    public BaseTest() { 
    } 

    public void initialize() { 
     mIsInitialized = true; 
    } 
} 

和它的子類Test

public class Test extends BaseTest { 
    public Test() { 
    } 

    public void initialize() { 
    } 
} 

謹供調用Test.initialize()設置mIsInitializedtrue無需調用super.initialize()。我同樣希望避免在超類中定義一個抽象函數。 這甚至可能嗎?

+2

這似乎是確切的場景你想使用方法的超級版本,因爲這是你將如何設置這樣的「默認」。你爲什麼如此反對呢? –

+0

對於你目前的限制,不,這是不可能的。 –

+0

您可以聲明方法'final',這樣基礎實現是唯一的實現(不能被覆蓋)。這不是你要求的,但可能會幫助你實現你的解決方案 – Cascader

回答

3

@rgettman et al。正在呼籲使用Template pattern。在這裏你明確了這樣一個事實,即子類可以通過特定的可重寫方法「鉤入」超類的行爲,這種方法不是initialize,這似乎違背了你的問題的精神。

您還可以使用AspectJ等面向方面的框架將各種不可見的行爲附加到方法調用中。

+0

謝謝你指出模板模式,這基本上是我想要避免的抽象函數(我剛剛學到的東西有一個名稱:)) –

+0

我希望有一些Java語言結構,它可以讓我做我想做的事情,而不必訴諸於面向方面的編程或代碼注入。你的答案與我想要做的最接近。如果沒有人出現Java構造,我會接受。 –

6

可以這樣做,但不能覆蓋initialize。在BaseTest類中,將initialize標記爲final,因此它不能被覆蓋。在initialize中,調用另一個方法來執行任何子類的初始化。

public final void initialize() { 
    mIsInitialized = true; 
    initializeFurther(); 
} 

你說沒有abstract方法。但是,initializeFurther只能設爲空。

protected void initializeFurther() {} 

然後,子類Test只需要重寫initializeFurther

public class Test extends BaseTest { 
    @Override 
    protected void initializeFurther() { 
     // Initialize Test here. 
    } 
} 

基類的initialize方法是保證設置mIsInitializedtrue,並Test可以實現initializeFurther然而就是了,不調用super.initialize()Test無法停止超類BaseTest進行初始化。

當在任何BaseTest實例上調用initialize時,initialize邏輯將始終運行。

+1

我不太明白這個答案。這個問題表明,開發人員希望將mIsInitialized的值更改爲在父類中聲明的true,而不用調用initialize方法。但是這個解決方案使得場最終並且已經初始化爲真。那麼,重要的是什麼?如果是這樣的話,我們可以簡單地將字段從一開始設置爲true。或者將該字段設置爲受保護並在子類中進行更改。我錯過了什麼嗎? –

+0

@EdwinDalorzo我認爲我的答案符合所有要求。子類方法不調用'super.initialize()'。 'BaseTest'中的'initialize'方法是'final',用於防止'Test'重寫'initialize'並執行諸如不調用'super.initialize()'的操作。這可以防止覆蓋方法阻止基類進行初始化。同時,鉤子方法'initializeFurther'被提供,這樣外部對'initialize'的調用仍然會得到子類的初始化,並且它還保證'BaseTest''' initialize'方法將按預期運行。 – rgettman

+0

@EdwinDalorzo我讀這個問題,如何防止子類'Test'阻止超類'BaseTest'初始化'mIsInitialized'爲'true'。如果沒有這個,'Test'可能會重寫'initialize'而不是調用'super.initialize',從而繞過'BaseTest'的初始化。 initialize的「默認行爲」被保留。 – rgettman

0

如果您阻止Test重寫BaseTest的initialize(),您可以直接調用BaseTest的initialize()。下面是一些測試代碼:

public class BaseTest { 
    private boolean mIsInitialized = false; 

    public BaseTest() { 
    } 

    public void initialize() { 
    mIsInitialized = true; 
    System.out.println(mIsInitialized); 
    } 

    public static void main(String[] args){ 
    Test test = new Test(); 
    test.initialize(); 

    } 

} 


class Test extends BaseTest { 
    public Test() { 
    } 
} 
+0

我認爲重點在於避免在超類中調用'initialize'。這正是這樣做的。不是嗎? –

+0

這就是我最初想的,但他仍然說他想在某個時候調用該方法:「我想要調用Test.initialize()...」如果他不想調用它,這可能會有所幫助兩次。 – user176692

相關問題