2011-07-20 64 views
6

基本上,我想要做的是force子類調用抽象超類方法(在子類中實現),所以我不必每個都明確寫出它我創建一個新的子類。如何強制子類調用抽象實現的方法

我曾經在超類的構造函數中寫過它,因爲我希望它在每個實現中強制它。

public abstract class SupahClass { 
    public SupahClass() { 
     doStuff(); // It IS executed when the subclass constructor is called 
     init(); // NOT executed, even though it's implemented 
    } 

    private void doStuff() { ... }   

    protected abstract void init(); 
} 

public class SomeSubClass extends SupahClass { 

    // The problem lies HERE: this is executed AFTER init() ... so it gets NULL again 
    private TextBox myTextBox = null; 

    public SomeSubClass() { 
     super(); // invokes the super constructor, so init() should be called 
     // I could call init(); here EACH time i create a new subclass... but no :) 
    } 

    @Override 
    public void init() { 
     this.myTextBox = new TextBox(); // Executed BEFORE its declared as null above 
    } 
} 

當然,超真的不能調用它,因爲它的一個抽象的(所以未定義)方法,但它的一個抽象類,所以它不能被實例化,它必須委託任務它的子類,那麼爲什麼他們不能稱之爲抽象但現在實施的方法?

編輯 見子類物業myTextBoxinit()實施

你認爲哪一個方法,我應該怎麼辦?在財產申報中取出= null(duhhh)

或刪除init()在超類和顯式調用它的子類的構造函數(這是我想避免的,因爲我必須把它寫的時間100% ..)

+1

這將工作。這顯然不是您的實際代碼 - 您的實際代碼在某種重要方面必須與此不同。爲什麼不發佈你的實際代碼,讓我們看看? –

+0

確實!看到我對Jon Skeet的回答和我更新的問題的評論:) – dominicbri7

回答

2

你可以通過改變你的宣言,以解決這個問題:

private TextBox myTextBox; 

賦值爲null沒有用處。如果沒有超類,它什麼都不會做,因爲無論如何字段初始化爲空。由於有一個超級類別,它的作用就像對槍響。所以,擺脫它。

+0

是的,這正是我所做的一刻來解決這個問題,但你讓我意識到它根本沒有用處,確實是一種不好的做法。 我什至不能想到它會有用的情況......我想我會在我使用它們的任何地方刪除這些作業。但除此之外,您如何看待我的當前實現(在構造函數中調用此類方法)? – dominicbri7

+0

正如每個人都會告訴你的那樣,這是一種危險的做法。它打開了一些非常棘手的錯誤(對部分構建的對象運行的方法,不安全的對象發佈等)。然而,它不會不可避免地導致這些錯誤 - 程序員仍然需要引入它們。如果從構造函數調用子類方法沒有優勢,我建議你永遠不要這樣做。但通常情況下,這是一種簡單明瞭的方式來獲得你想要的行爲,而不是直截了當的選擇。所以,有一個判斷電話的價值是否超過了錯誤的風險。 –

+0

這是一個依賴於上下文的判斷調用 - 關於類中不變量的複雜程度,在代碼庫上工作的程序員的熟練程度,類是廣泛擴展還是侷限於系統的一小部分,這是一個具體的問題,我不能給你一個一般的答案。 Jon Skeet當然可以:)。 –

8

我不能重現這一點。 init()將調用,假設沒有任何例外情況被首先拋出。簡短但完整的示例:

abstract class Superclass { 
    public Superclass() { 
     init(); 
    } 

    protected abstract void init(); 
} 

class Subclass extends Superclass { 
    public Subclass() { 
     super(); 
    } 

    @Override 
    public void init() { 
     System.out.println("Subclass.init called"); 
    } 
} 

public class Test {  
    public static void main(String[] args) throws Exception { 
     new Subclass(); 
    } 
} 

按預期打印「Subclass.init called」。我懷疑你沒有向我們展示過的代碼有其他錯誤。

請注意,在構造函數中調用虛擬方法是一項風險業務 - 子類尚未初始化 - 例如,所有變量都將具有其默認值。這通常是一種需要避免的模式。

+1

即將表明這一點,但沒有恥辱被Jon Skeet毆打 – Leon

+0

你是完全正確的..我認爲Init從未被召喚,因爲在某個時刻當它應該被初始化時,子類屬性爲null。 當你說這是一個危險的業務時,你是對的兩倍,因爲子類不會被初始化:那正是我的問題。看到我最新的問題在最後的更多信息,我真的很喜歡你的意見,你認爲我應該使用哪種方法.. :) – dominicbri7

2

抽象類可以調用抽象方法。

0

您是否使用過調試器來了解代碼在做什麼?

施工的順序是基類 2.初始化派生類的所有成員 3.構造派生類的 1.構造函數。

在您的情況下,第1步初始化成員(在派生類的init中 - 通過多態調用調用),但是第2步將其設置爲null。

相關問題