2012-04-11 5 views
2

Hier ist das, was ich zu tun habe versucht:Downcasting und Polymorphie ohne Verwendung von instanceof? (Java)

class Foo { 
    private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects 
    //... 
    void process(int wIndex) { 
     process(things.get(wIndex); 
    } 

    private void process(WidgetA w) { 
     //Do things 
    } 
    private void process(WidgetB w) { 
     //Do other things 
    } 
    private void process(WidgetAB w) { 
     //Do completely different things 
    } 
} 

abstract class Widget { 
    //... 
} 

class WidgetA extends Widget { 
    //... 
} 
class WidgetB extends Widget { 
} 
class WidgetAB extends WidgetA { 
} 

Grundsätzlich ist eine separate Klasse bekommt einen Array-Index von Benutzereingaben, und übergibt sie an den Prozess (int) -Methode, die ist soll eine typspezifische process() -Methode auslösen, um das Objekt am übergebenen Index zu verarbeiten. Das Problem ist, dass die Objekte als Widget-Objekte behandelt werden, nicht als WidgetA usw. Ich könnte die Typen mit instanceof durchlaufen, ich denke, aber ich versuche, das zu vermeiden. Die Logik in den process() - Methoden muss auf private Felder in der Foo-Klasse zugreifen. Daher ist es möglicherweise nicht die beste Idee, sie in die Widget-Unterklassen zu verschieben.

Die Frage ist also, gibt es eine Möglichkeit für die richtige process() -Methode für einen bestimmten Widget-Untertyp aufgerufen werden, ohne instanceof?

+0

mögliches Duplikat von [Wird diese Verwendung des "instanceof" -Operators als schlechtes Design angesehen?] (Http://stackoverflow.com/questions/8841577/is-this-use-of-the-instanceof-operator-conspired-) schlechtes Design) –

Antwort

3

Ja, werfen Sie einen Blick auf das Besuchermuster - auch bekannt als Doppelversand.

0

Eine andere mögliche Lösung ist die Verwendung von Javas Reflektions-APIs. Beispiel:

class Foo { 
    private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects 
    //... 
    void process(int wIndex) { 
     Widget theWidget = things.get(wIndex); 
     try { 
      Class type = theWidget.getClass(); 
      Class[] arg_types = new Class[]{type}; 
      this.getMethod("process", arg_types).invoke(this, theWidget); 
     } catch (Exception e) { 
      //Could be SecurityException or NoSuchMethodException 
     } 
    } 

    private void process(WidgetA w) { 
     //Do things 
    } 
    private void process(WidgetB w) { 
     //Do other things 
    } 
    private void process(WidgetAB w) { 
     //Do completely different things 
    } 
} 

abstract class Widget { 
    //... 
} 

class WidgetA extends Widget { 
    //... 
} 
class WidgetB extends Widget { 
} 
class WidgetAB extends WidgetA { 
} 

Das hier Problem ist, dass Sie eine process() Methode für jede Art von Objekt in der things Liste oder eine Ausnahme definiert haben, müssen zur Laufzeit geworfen werden. Der Compiler warnt Sie nicht, wenn Sie eine Implementierung vermissen.