Vereinfachung instanceof

Status
Nicht offen für weitere Antworten.

Alex04

Bekanntes Mitglied
Hallo,
ich hätte ne frage zu nem sehr unschönen Code-Teil in einem Programm:

Code:
...
while(it.hasNext()) {
            Object current = it.next();
            System.out.println(current.toString());

            if(current instanceof StartImpl) {
                //Start node
                this.transformStartImpl((StartImpl) current);
            }

            else if(current instanceof EndImpl) {
                //Transform EMF end node to generator end node
                this.transformEndImpl((EndImpl) current);
            }

            else if(current instanceof ActivityImpl) {
                //Transform EMF activity to generator activity
                this.transformActivityImpl((ActivityImpl) current);
            }

            else if(current instanceof ControlFlowImpl){
                //Transform EMF ControlFlow to generator ControlFlow
                this.transformControlFlowImpl((ControlFlowImpl) current);
            }

            else if(current instanceof UIActionImpl) {
                //Transform EMF UIAction to generator UIAction
                this.transformUIActionImpl((UIActionImpl) current);
            }

            else if(current instanceof ANDImpl) {
                //Transform EMF AND to generator AND

            }

            else if(current instanceof XORImpl) {
                //Transform EMF XOR to generator XOR

            }

            else if(current instanceof DomainModelActionImpl) {
                //Transform EMF DomainModelAction to generator DomainModelAction
                this.transformDomainModelActionImpl((DomainModelActionImpl) current);
            }

            else if(current instanceof UseCaseImpl){
                this.transformUseCaseImpl((UseCaseImpl) current);
            }
        }
...

Kann man das nicht irgendwie etwas schöner lösen?
Jede transform Methode hat eine andere Funktionalität. Außerdem gibt es auch Objekte in current die nicht transformiert werden müssen, d.h das keine transform Methode aufgerufen wird.

Wäre für jede Vereinfachung dankbar!
Lg
Alex
 
S

SlaterB

Gast
du könntest in jeder dieser Klassen eine Interface-Methode implementieren, die enweder die korrekte andere Methode aufruft,
oder einen Enum-Typ-Wert zurückgibt, der für ein switch/ für eine Map genutzt wird,

alles in allem kann das aber vom Quellcode her nicht kürzer werden als dieses if/ else,
nur die Performance ließe sich gegenüber instanceof steigern, aber darauf kommt es wohl nicht so an?

irgendwo muss die Verknüpfung aus Klasse und Methode nunmal stehen, weniger als 1-3 Zeilen pro Fall ist schwer
 

hdi

Top Contributor
[HIGHLIGHT="Java"]public abstract class TransformImpl{

public abstract void transform ( whatever "this" is in your code );
}

public class StartImpl extends TransformImpl{

@Override
public abstract void transform ( whatever "this" is in your code ){
// ...
}

// analog zu allen anderen Klassen[/HIGHLIGHT]

dann:

[HIGHLIGHT="Java"]while(it.hasNext(){
Object next = it.next();
if(next instanceof TransformImpl){
((TransformImpl)next).transform(this);
}
}[/HIGHLIGHT]
 

0x7F800000

Top Contributor
mit ein wenig Polymorphie und Generics geht so einiges, allerdings geht aus dem code ziemlich nichts hervor, außer dass es hässlich ist. Da fallen mir leider auch keine konkreteren Tipps zum design ein, außer dem Vorschlag es etwas hübscher zu machen. Wenn es möglich ist, sollte jedes dieser objekte sich irgendwie "selbst transformieren" was auch immer dieses "transformieren" heißen soll, etwa so:
[HIGHLIGHT="Java"]
//interface
interface Transformable{
void transformYourself(Transformator t);
}

//viele viele klassen, die mit instanceof unterschieden werden
class A implements Transformable{
void transformYourself(Transformator t){
stuff=t.tellMeSomeImportantStuffHowToTransformMyself();
//sich selbst umformen
}
}

class B implements Transformable{...
...
}

//liste füllen
Collection<Transformable> list=new LinkedList<Transformable>();
list.add(new A());
list.add(new B());

//irgendwie umtransformieren
Transformator trafo=new ExteremelyIntelligentTransformatorOfWhatever();
for(Transformable e:list){
e.transformYourself(trafo);
}
[/HIGHLIGHT]
sowas in der Art...

edit: hdi war schneller...
 

0x7F800000

Top Contributor
Wäre das dann sowas?!:confused:
[HIGHLIGHT="Java"]
Transformator{
void transform(StartImpl x){
...
}
void transform(EndImpl y){
...
}
}

interface Transformable{
void invokeTransformationMethod(Transformator t);
}

StartImpl implements Transformable{
void invokeTransformationMethod(Transformator t){
t.transform(this);
}
}

EndImpl implements Transformable{
void invokeTransformationMethod(Transformator t){
t.transform(this);
}
}
[/HIGHLIGHT]
Ich kann nur hoffen, dass ich das jetzt falsch verstanden hab, denn das wäre imho nur eine Krücke dafür:
[HIGHLIGHT="Java"]
public class _ {
static class X{}
static class A extends X{}
static class B extends X{}

public static void f(A a){ System.out.println("a"); }
public static void f(B a){ System.out.println("b"); }
public static void f(X a){ System.out.println("x"); }

public static void main(String[] args){
X x=new B();
f(x); //gibt "x" und nicht etwa "b" aus
}
}
[/HIGHLIGHT]
bzw. eigentlich keinen millimeter besser, als diese gruselige instanceof-abfrage, nur auf 100 Klassen statt einer verteilt... Oder?
 

Wildcard

Top Contributor
Sieht dann in etwa so aus:
[HIGHLIGHT="Java"]current.accept(this);

visit(StartImpl impl){
//do something
}

visit(EndImpl impl){
//do something
}[/HIGHLIGHT]

In den 'Impls' steht dann eine einfache, generelle visit Methode:
[HIGHLIGHT="Java"]
public void accept(Visitor visitor){
visitor.visit(this);
}[/HIGHLIGHT]
Man umgeht damit die Single Dispatch Limitierung und spart sich das instanceof.
Das traversieren über die Objekte kann ebenfalls direkt in die visit Implementierung verlagert werden.
Somit baust du in dein Model eine Art wiederverwendbarer 'Switch' und die Möglichkeit über die Objekte zu traversieren.
 

Landei

Top Contributor
Auch nicht viel hübscher:
Code:
interface TransHelper { void trans(Object o); }

private static Map<Class<?>, TransHelper> map = new HashMap<Class<?>,TransHelper>();
{
    map.put(StartImpl.class, new TransHelper(){ public void trans(Object o){transformStartImpl((StartImpl) o)}}); 
    map.put(EndImpl.class, new TransHelper(){ public void trans(Object o){transformEndImpl((EndImpl) o)}}); 
    ...
}

...
while(it.hasNext()) {
            Object current = it.next();
            Class<?> clazz = current.clazz;
            if (map.contains(clazz) {
                 map.get(clazz).trans(current);
            } 
}
 

Landei

Top Contributor
Das Visitor-Pattern hat auch Nachteile, insbesondere ist es aufwendig, zusätzliche Methoden hinzuzufügen. In diesem Fall ist es schwierig zu sagen, was die bessere Lösung ist, weil das Beispiel aus dem Kontext gerissen ist. Meine Variante kann sicher auch noch verbessert werden (ich hatte mal in einem Thread was über eine DependentMap gepostet, dann wären wir schon mal typsicher).

Prinzipiell kann man hier gut sehen, dass in Java eine Art "switch-statement für Typen" fehlt (andere Sprachen haben das als "Pattern Matching", z.B. Haskell, Erlang und ihr wisst schon welche noch...), wodurch das Visitor-Pattern in den meisten Fällen überflüssig ist.
 

Wildcard

Top Contributor
Das Visitor-Pattern hat auch Nachteile, insbesondere ist es aufwendig, zusätzliche Methoden hinzuzufügen. In diesem Fall ist es schwierig zu sagen, was die bessere Lösung ist, weil das Beispiel aus dem Kontext gerissen ist.
Da kann ich nur zustimmen. Ohne zusätzlich Randbedingungen ist ein Visitor erstmal eine saubere Lösung, aber je nach Kontext kann es auch die falsche Wahl sein.
 

Alex04

Bekanntes Mitglied
Hallo,
vielen Dank schonmal für eure Hilfe,
Problem ist, das ich es gerne ohne Polymorphismus lösen möchte, da die Klassen wie StartImpl usw. nicht verändert werden sollen!
Hier fällt dann ja auch das Visitor pattern raus!
Die Lösung von Landei passt damit am besten und ich werde diese mal versuchen...

Besten Dank nochmal
Lg
Alex
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
Ocram Variablen Vereinfachung einer Bedingung Java Basics - Anfänger-Themen 18
E Klassen Abstracte Classe als Vereinfachung Java Basics - Anfänger-Themen 4
C Vereinfachung eines Java Programmes Java Basics - Anfänger-Themen 5
G Vereinfachung einer if Konstruktion Java Basics - Anfänger-Themen 8
S Frage zur Vereinfachung Java Basics - Anfänger-Themen 2
D Vereinfachung dieses Programms Java Basics - Anfänger-Themen 11
NeoLexx Abfrage mit instanceof führt zu unerwarteten Wert Java Basics - Anfänger-Themen 9
C Warum funktioniert 'instanceof' bei generics nicht? Java Basics - Anfänger-Themen 4
S Gibt es eine Funktion, die gewissermaßen eine Reihe von instanceOf() vereinheitlicht? Java Basics - Anfänger-Themen 19
J instanceof Operator Java Basics - Anfänger-Themen 3
G instanceof in Generic Java Basics - Anfänger-Themen 7
A instanceof-if-else-Anweisungen eleganter lösen Java Basics - Anfänger-Themen 5
B instanceof Java Basics - Anfänger-Themen 9
L Best Practise - 'instanceof' oder nicht. Java Basics - Anfänger-Themen 7
Luk10 instanceof Class<T> Java Basics - Anfänger-Themen 6
I if (listenObjekt instanceof meinObjekt.class) Java Basics - Anfänger-Themen 5
A ArrayList-iteration mit Prüfung auf instanceof durch switch case? Java Basics - Anfänger-Themen 13
K Polymorphie und instanceOf Operator Java Basics - Anfänger-Themen 6
M Compiler-Fehler instanceof compiler-error Java Basics - Anfänger-Themen 2
A Alternative instanceof Java Basics - Anfänger-Themen 3
0 Vererbung - instanceof Java Basics - Anfänger-Themen 20
J this instanceof Class<Object> Java Basics - Anfänger-Themen 1
D HasMap mit JComponents mit instanceof Java Basics - Anfänger-Themen 3
K Equals,Instanceof und "==" Java Basics - Anfänger-Themen 7
A Datentypen instanceof VS Class - Vergleich Java Basics - Anfänger-Themen 4
S Bessere Lösung zu häufigem instanceof Java Basics - Anfänger-Themen 25
A Besser als instanceof Java Basics - Anfänger-Themen 6
E instanceof vs class==class Java Basics - Anfänger-Themen 5
B instanceof Prüfung für generische Typen Java Basics - Anfänger-Themen 5
S instanceof Comparable...geht nicht? Java Basics - Anfänger-Themen 20
K instanceof Java Basics - Anfänger-Themen 22
G Mit "instanceof" sich selbst Fragen? Java Basics - Anfänger-Themen 4
S Instanceof umkehren Java Basics - Anfänger-Themen 2
E Negative Abfrage auf instanceof Java Basics - Anfänger-Themen 3
D if (event.target instanceof TextField) Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben