2012-01-03 59 views
2

我想使用多態,使基於它的類對象的不同處理動態多態調用,如下所示:強制執行與一般的父類型的輸入參數

public class GeneralStuff { 
    private int ID; 
} 

public class IntStuff extends GeneralStuff { 
    private int value; 

    public void setValue(int v) 
    { 
     value = v; 
    } 

    public int getValue() 
    { 
     return value; 
    } 
} 

public class DoubleStuff extends GeneralStuff { 
    private double value; 

    public void setValue(double v) 
    { 
     value = v; 
    } 

    public double getValue() 
    { 
     return value; 
    } 
} 

public class ProcessStuff { 

    public String process(GeneralStuff gS) 
    { 
     return doProcess(gS); 
    } 

    private String doProcess(IntStuff i) 
    { 
     return String.format("%d", i.getValue()); 
    } 

    private String doProcess(DoubleStuff d) 
    { 
     return String.format("%f", d.getValue()); 
    } 
} 


public class Test { 
    public static void main(String[] args) 
    { 
     IntStuff iS = new IntStuff(); 
     DoubleStuff dS = new DoubleStuff(); 
     ProcessStuff pS = new ProcessStuff(); 

     iS.setValue(5); 
     dS.setValue(23.2); 

     System.out.println(pS.process(iS)); 
     System.out.println(pS.process(dS)); 
    } 
} 

然而,這是不行的,因爲調用doProcess(gS)預計爲署名doProcess(GeneralStuff gS)的方法。

我知道在ProcessStuff類中我只能有兩個暴露的多態處理方法,但實際情況不會允許它,因爲我在現有庫機制的約束下工作;這只是一個人爲測試的例子。

我當然可以,定義process(GeneralStuff gS)

public String process(GeneralStuff gS) 
{ 
    if (gS instanceof IntStuff) 
    { 
     return doProcess((IntStuff) gS); 
    } 
    else if (gS instanceof DoubleStuff) 
    { 
     return doProcess((DoubleStuff) gS); 
    } 
    return ""; 
} 

它的工作原理,但似乎我不應該這樣做(加,編程警方會串燒我要以這種方式使用的instanceof )。

有沒有辦法,我可以強制執行以更好的方式多態調用的方法嗎?

在此先感謝您的幫助。

回答

0

也許,最好在ProcessStuff到重載process方法:

public class ProcessStuff { 

    private String process(IntStuff i) { 
     return String.format("%d", i.getValue()); 
    } 

    private String process(DoubleStuff d) { 
     return String.format("%f", d.getValue()); 
    } 
} 
0

定義一個GeneralStuff作爲一個抽象類,與在所述繼承類填充在doProcess方法(摘要)。這樣可以避免instanceof值等問題。或者,你可以做什麼是由βнɛƨнǤʋяʋиɢ建議,但你仍然要定義一個過載每個特定的類,而在我的你只是直接調用它。

所以我的建議是: 公共抽象類GeneralStuff { private int ID;

public abstract String process(); 
} 

public class IntStuff extends GeneralStuff { 
    private int value; 

    public void setValue(int v) 
    { 
     value = v; 
    } 

    public int getValue() 
    { 
     return value; 
    } 

    @override 
    public String process(){ 
     return String.format("%d", getValue()); 
    } 
} 

public class DoubleStuff extends GeneralStuff { 
    private double value; 

    public void setValue(double v) 
    { 
     value = v; 
    } 

    public double getValue() 
    { 
     return value; 
    } 

    @override 
    public String process(){ 
     return String.format("%f", getValue()); 
    } 
} 

public class Test { 
    public static void main(String[] args) 
    { 
     IntStuff iS = new IntStuff(); 
     DoubleStuff dS = new DoubleStuff(); 
     ProcessStuff pS = new ProcessStuff(); 

     iS.setValue(5); 
     dS.setValue(23.2); 

     System.out.println(iS.process()); 
     System.out.println(dS.process()); 
    } 
} 
1

編譯器會抱怨有很好的理由。有沒有保證您的GeneralStuff對象是IntStuffDoubleStuff。它可以是一個普通的GeneralStuff或任何其他分機的GeneralStuff,這是你還沒有在你的process方法與instanceof覆蓋的情況下(除非返回空String是所期望的行爲)。

是不可能將process方法移入GeneralStuff類,並在擴展中覆蓋它?

另一種可能的解決方案是一種複合ProcessStuff類的在其中插入一個IntStuffProcessDoubleStuffProcess,...實例。每個實例仍然會有instanceof檢查以決定它們是否可以處理傳遞給它們的對象GeneralStuff,但這至少可以擴展/維護,然後構造一個大實例

+0

在實際應用中,參數對象('IntStuff','DoubleStuff')被打包爲'GeneralStuff'的實例到'Bundle'對象中,並傳遞給另一個對象('ProcessStuff')對象進行處理,其中參數對象被抽出並根據它們的實際類型採取不同的動作。因此,我實際上沒有在直接調用ProcessStuff中提供重載的過程方法的選項(由@βнɛƨнǤʋяʋиɢ建議),並且將'process'方法移入'GeneralStuff'也可能不是一個選項由你和@codegrabber建議)。 – 2012-01-04 06:35:47

3

您正在查找的動態分派的類型沒有使用反射在Java中是不可能的。 Java那樣的鏈接在基於聲明的類型編譯時(因此,即使一個方法被重載,調用實際的方法是基於聲明的類型變量沒有運行時類型)。因此,您可能會使用instanceof,或者使用反射,或將處理方法放入對象本身(這是「做」的方式來做到這一點,但通常並不合適或不可取)。

一個潛在的替代方法是創建地圖由一流的加工對象的,如:

Map<Class<? extends GeneralStuff>,Processor> processors; 

public String process(GeneralStuff stuff) 
{ 
    Processor processor = processors.get(stuff.getClass()); 
    if (processor != null) 
    { 
    return processor.process(stuff); 
    } 
} 

public interface Processor 
{ 
    public String process(GeneralStuff stuff); 
} 

public class IntegerProcessor implements Processor 
{ 
    public String process(GeneralStuff stuff) 
    { 
    return String.format("%i",((IntegerStuff) stuff).getValue()); 
    } 
} 

然而,你的具體的例子,採用的String.format對象作爲參數,所以你能避免這個問題全在GeneralStuff中有getValue和getFormatString方法,這些方法在特定的子類中被覆蓋。

+0

這個工作,並且是基於類的一個聰明的重定向的方式。我相信'Map'也可以用來指導流程到'ProcessStuff'類中的不同方法。謝謝! – 2012-01-04 06:33:35

2

你實際上是在正確的軌道上,你確實需要在這種情況下使用反射。你正在尋找的是double dispatch,因爲你想要在stuff參數的動態類型上完成調度。

這種類型的開關動態型並不像您想象的那麼難得。參見this javaworld tipe,它反映在visitor pattern

+0

偉大的參考!謝謝。 – 2012-01-04 06:55:11

相關問題