| 

.NET C# Java Javascript Exception

1
Hallo,

ich bin aktuell ein wenig dabei mich in JAVA zu bewegen. Aktuell bin ich dabei mit ein Objektmodell für Kommandosätze zu bauen. Da ich normaler Weise nur .NET Anwendungen entwickle habe ich aktuell ein wenig Probleme mit dem Type-Casting von JAVA umzugehen.

Ich versuche mein Problem mal ein wenig zu veranschaulichen.

Ich habe ein BasisCommand, sowie ein CommandA und CommandB welche je von BasisCommand abgeleitet sind. Nun gibt es eine Funktion die aus einem Datenblock ein Command baut. Dieses kann CommandA aber auch CommandB sein. Die Funktion erzeugt also ein beliebiges von BasisCommand abgeleitet Objekt.

Nun gibt es eine weitere Funktion die ein beliebiges Command entgegen nimmt und dies weiterverarbeitet.

Nun habe ich das Problem, dass ich in Java ein BasisCommand nicht mehr in CommandA "zurück gecastet" bekomme. Wenn ich es richtig verstanden habe, ist das auch so gewollt. Daher gehe ich einfach mal davon aus, dass in meiner Grundidee ein - mehr oder weniger schwerer - Fehler ist.

Im .NET Umfeld wäre der Parameter der Funktion einfach vom Typ BasisCommand und ich würde, je nach tatsächlichem Type, das Objekt entsprechend casten um so auf die Funktionen eund Eigenschaften zugreifen zu können.

Wie sollte solch ein Konstrukt in JAVA am besten aussehen, bzw. wo ist mein Denkfehler?

P.S.: Bei Bedarf kann ich das ganze auch gerne per Code abbilden wenn das besser zu verstehen ist.

Grüße

[UPDATE]

Ich habe das Scenario einmal stark vereinfach gerade runtergetippt. Das Problem liegt hier dabei, dass eine zentrale Stelle (read()) ein beliebiges BaseCommand hervorbringt. Dies soll dann weiterverarbeitet werden. Wobei die Definition von read() nicht in Stein gemeißelt ist.

public class BaseCommand
{
public int CommandType;
public int getCommandType()
{
return CommandType;
}

public int CommandDirection;
public String DataContainer;
public String getDataContainer()
{
return DataContainer;
}

public String buildMessage()
{
return "" + CommandType + ";" + CommandDirection + ";" + DataContainer;
}
}

public class CommandA extends BaseCommand
{
public CommandA()
{
}

@Override
public int getCommandType()
{
return 1337;
}

public String parseMetaData()
{
return doStuff(DataContainer);
}
}

public class Interpreter()
{
public static BaseCommand read()
{
return new CommandA();
}

public static executeCommand(BaseCommand cmd)
{
switch( cmd.getClass().getName() )
{
case "CommandA":
CommandA command = (CommandA)cmd; // Cast nicht möglich.
command.doStuff();
break;
}
}
}
News:
09.09.2014
Slashi 409 2 8
Slashi 409 2 8
Ein bisschen Code wäre nicht schlecht, bin mir grad nicht sicher ob ich dich richtig verstanden habe.
phg 09.09.2014
Danke für den Code - aber wo ist jetzt die Stelle, wo Du Probleme mit dem Cast hast? Der switch wird nicht funktionieren, aber das liegt daran, daß Du über Class-Objekte nicht switchen kannst (http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html). Soweit ich weiß, könntest Du das in .NET aber auch nicht.
Matthias Hlawatsch 10.09.2014
Ich hab den Code mal erweitert.
Slashi 10.09.2014
1 Antwort
1
Also ich musste schon einiges machen damit der Code jetzt läuft ;)
Du hast Java 1.7 denke ich, sonst würde die Switch Anweisung nicht funktionieren da vor 1.7 Switch kein String aufnehmen konnte.

Davon abgesehen würde ich das ganze anders lösen, solche Konstrukte sind gelinde gesagt Spaghetticode Konstrukte.

Wie definiert man denn nun eine Liste richtig in Java?

List<String> liste = new ArrayList<String>();


Genauso machst du es doch auch hier, du definierst die Elternklasse und die Verarbung übernimmt den Rest, wenn du eine Kindklasse (CommandX) übergibst, ist es immernoch ein Erbe von BaseCommand und kann eben so behandelt werden.

public class BaseCommand
{
public int CommandType;
public int getCommandType()
{
return CommandType;
}

public int CommandDirection;
public String DataContainer;
public String getDataContainer()
{
return DataContainer;
}

public String buildMessage()
{
return "" + CommandType + ";" + CommandDirection + ";" + DataContainer;
}

public String parseMetaData()
{
return "Base";
}
}

public class CommandA extends BaseCommand
{
public CommandA()
{
System.out.println("Commando a");
}

@Override
public int getCommandType()
{
return 1337;
}

public String parseMetaData()
{
return "TestA";
}
}

public class CommandB extends BaseCommand
{
public CommandB()
{
System.out.println("Kommando B");
}

@Override
public int getCommandType()
{
return 1337;
}

public String parseMetaData()
{
return "TestB";
}
}

public class CommandC extends BaseCommand
{
public CommandC()
{
System.out.println("Kommando C");
}

@Override
public int getCommandType()
{
return 1337;
}

}

public class Interpreter {

public static void main(String[] args) {
executeCommand(new CommandA());
executeCommand(new CommandB());
executeCommand(new CommandC());
}

public static BaseCommand read()
{
return new CommandA();
}

public static void executeCommand(BaseCommand cmd)
{

System.out.println(cmd.parseMetaData ());

}

}


Du brauchst weder mit Switch-Case arbeiten, noch mit einem If-Then-Else oder andere Konstrukte.

Idealerweise ist BaseCommand nur das Interface und es wird nichts ausprogrammiert, alle Methoden müssen vorhanden sein (hier parseMetaData() ) und die Klassen die Erben, implementieren diese.

Oder auch nicht, dann wird eben die Methode von der Elternklasse genommen, klappt auch, siehst du in meinem Beispiel auch.

Ich hoffe ich hab deine Frage richtig verstanden :)
10.09.2014
Lord_Pinhead 778 1 8
Hi, danke erst einmal für die Mühe. Der Code ist im Editor zusammen getippt und sollte soll nur das "Problem" veranschaulichen.

In deiner Änderung wird eine Funktion aufgerufen, die tatsächlich im BaseCommand existiert. Ein CommandX wird also einfach in seine Basis gecastet (upcasting). Was ich möchte ist aber die andere Richtung zu gehen. Nur das Downcasting so nicht möglich ist.

So könnte ich mir auch jede Ableitung sparen und das "Problem" so lösen, dass ist aber nicht Ziel des Spiels.

In Wahrheit handelt es sich beim BaseCommand tatsächlich um eine 'abstract class'.
Slashi 10.09.2014
1
Ah, das willst du eigentlich. Also ja, Downcasting ist natürlich erlaubt in Java, aber nur wenn es eine Chance gibt das es zur Laufzeit auch funktionieren wird. Von einem String in einen Integer casten geht also nicht. An sich ändert sich da aber nichts denke ich, du gibst ja die Basisklasse an und wenn dann ein Erbe kommt geht es und wenn nur die Basisklasse kommt, ist es genauso legitim. Aber zu Downcasting: http://stackoverflow.com/questions/380813/downcasting-in-java
Lord_Pinhead 10.09.2014

Stelle deine Java-Frage jetzt!