2012-01-03 85 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