2011-01-09 66 views
3

我有一個抽象的模板方法:Java的重載方法

class abstract MyTemplate 
{ 
    public void something(Object obj) 
    { 
     doSomething(obj) 

    } 

    protected void doSomething(Object obj); 

} 

class MyImpl extends MyTemplate 
{ 

    protected void doSomething(Object obj) 
    { 
     System.out.println("i am dealing with generic object"); 
    } 

    protected void doSomething(String str) 
    { 
     System.out.println("I am dealing with string"); 
    } 
} 


public static void main(String[] args) 
{ 
    MyImpl impl = new MyImpl(); 
    impl.something("abc"); // --> this return "i am dealing with generic object" 

} 

如何打印 「我處理字符串」 W/O在DoSomething的(obj對象)使用的instanceof?

謝謝,

+1

從OO的角度來看,我會覺得很難,爲什麼我需要這樣的構造。 Object類的實例沒有太多的行爲,爲什麼將它們作爲參數傳遞? –

+0

同上Horst說什麼。如果您要定義您的基類以在其方法簽名中使用類型「對象」,那麼您確實不應該假定處理特定的類型。我建議用泛型來定義MyTemplate的類層次結構。 – whaley

回答

0

它是不可能的。 MyImpl中的doSomething(Object obj)是重寫MyTemplate中的doSomething的方法。

在MyImpl的doSomething(Object obj)中使用instanceof-operator。無論如何,這是更好的風格。

+1

我認爲一般情況下,instanceof的用法暗示可能會違反Liskov替換原則(LSP)。 –

+0

在這種情況下,子類似乎對特殊類型的對象「優化」,儘管它能夠處理所有對象。我們需要一些區別,這是由instanceof完成的。而且我也不喜歡這個原則,因爲繼承一些東西而不是原始對象是恕我直言的一種改變程序的好方法。也許我只是不明白這個原則。 – Daniel

+0

對於這些類型的事物,多態性應該優於instanceof。此外,如果您正在檢查(並潛在地轉換爲)方法中的特定子類型,那麼您的方法應該已接受子類型作爲參數,而不是超類型(可以通過OP提供的示例中的泛型完成)。 – whaley

0

總之,你不能。其他答案解釋了原因。另一種方法可能是使用泛型,並依賴抽象類的特定子類來處理字符串(或其他特定的類)。例如:

abstract public class MyTemplate<T> { 
    abstract public void doSomething(T t); 
} 

public class MyTemplateImpl extends MyTemplate<Object> { 

    @Override 
    public void doSomething(Object o) { 
     System.out.println("Dealing with a generic Object"); 
    } 
} 

public class MyTemplateImplForStrings extends MyTemplate<String> { 
    @Override 
    public void doSomething(String s) { 
     System.out.println("dealing with a String"); 
    } 
} 

這意味着你的調用代碼是這樣的:

MyTemplateImplForStrings template = new MyTemplateImplForStrings(); 
template.doSomething("hello"); //prints ""dealing with a String" 

MyTemplate<String> template = new MyTemplateImplForStrings(); 
template.doSomething("hello"); //prints ""dealing with a String" 

注意:你要避免使用抽象基作爲您的參考鍵入,除非用String參數化它;否則,您將在運行時爲ClassCastExceptions打開大門,編譯器應該提醒您。

0

java編譯器使用方法參數的編譯時類型來創建方法調用,在您的示例中它是Object而不是String。方法調用會忽略參數的運行時類型。

如果您控制所有輸入類或使用reflection,您可以嘗試visitor pattern,這是緩慢/複雜且容易出錯的。