Bessere Lösung zu häufigem instanceof

Status
Nicht offen für weitere Antworten.

StefanTmp

Mitglied
Hallo zusammen,

folgendes Problem:
ich initialisiere eine hashMap mMap mit String handle als key und UIComponent als value. UIComponent ist eine Klasse mit einem handle auf sich selbst, einem handle auf seinen parent und dem javax.swing entsprechenden JComponent, also JButton usw.
In einer auf java basierenden 4GL kann man dann Funktionen wie getText(String handle) aufrufen, die dann wiederrum auf Javaseite folgende Funktion aufruft:

Java:
static public String getText(String pComponentId) throws Exception {
		if ((mMap.get(pComponentId).getMObject()) == null) {
			throw new Exception("getText: " + pComponentId + " not available");
		}
		String lResult = null;
		4LUIComponent lComponent = mMap.get(pComponentId);
		if (lComponent.getMObject() instanceof JTextField) {
			JTextField lField = (JTextField) lComponent.getMObject();
			lResult = lField.getText();
		} else if(lComponent.getMObject()instanceof JButton){
			JButton lButton = (JButton) lComponent.getMObject();
			lResult=lButton.getText();
		}
		return lResult;
	}
Meine Frage ist nun: Gibt es einen schöneren Weg, als in jeder von mir zur Verfügung gestellten Funktion mit instanceof zu prüfen, um welche Komponente es sich handelt? Da man ja nicht nur von Textfeldern und Buttons den Text holen kann, und noch weitere Funktionen wie setText(String handle) dazukommen sollen, wär mir ein schönerer Weg recht.

Danke für eure Hilfe.
Grüße
StefanTmp
 
S

Spacerat

Gast
Hab' jetzt die API nicht im Kopf, aber möglicherweise implementieren die Komponenten ja ein Interface, welches die Methode "getText()" anbietet. Dann könnte man auf dieses testen und hätte nur noch ein "if". Ansonsten hilft Reflection.
Java:
try {
  Method m = comp.getClass().getMethod("getText");
  String text = (String) m.invoke(comp);
} catch(Exception e) {
  // nothing
}
Anm.: Der Code benötigt Java 5+ und ist nicht wirklich sauber implementiert.
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
wenn du von jeder Klasse eine eigene Subklasse erstellst, könntest du eine einheitliche Methode per Interface vorgeben,

anderenfalls könntest zu jedem Objekt irgendwo ein zweites hinterlegen,
map.put(textField3,new JCompHandler(textField3);
dieses per Map abfragen und dann an den Handler für die verschiedenen Komponenten die einheitliche Methode getText() aufrufen,
jeder Handler muss das nur an seine Komponente korrekt weiterleiten,

vielleicht kann UIComponent diese Aufgabe übernehmen oder eine Subklasse davon
 
B

bygones

Gast
getMObject() liefert das einheitliche interface zurueck - simple und einfach :)

und dann nichts per reflection sondern einfach plain old java
 

StefanTmp

Mitglied
@SlaterB Bei deinem zweiten Vorschlag würde ich gern nochmal nachhaken:

ich erstelle eine zweite Map, die meine eigens erstellte Klasse JCompHandler beinhaltet. In dieser Klasse ist dann die Methode getText implementiert?
Bei der Weiterleitung bin ich mir auch unsicher, könntest du mir ein Beispiel geben?

Danke euch
Gruß
StefanTmp
 
S

SlaterB

Gast
in der Klasse JCompHandler könnten n Klassenattribute vorliegen
JTextField tf;
JButton b;
..

durch den Konstruktor wird eines davon gesetzt, getText sieht etwa so aus:

getString() {
if (b != null) {
return b.getText();
} else ..
}

Vorteil: einfache if null-Abfragen statt teure instanceof, und in eine separate Klasse verschoben, da stören paar if/else Konstrukte weniger als im Hauptcode ;),
zumal an verschiedenen Stellen wiederverwendbar

-----

wenn es ganz ohne if gehen soll, dann brauchst du pro Komponentenart eine Subklasse, mit nur einem Klassenattribut und getString() z.B.
getString() {
return b.getText();
}
für JButtonHandler,
andere Klassen JTextFieldHandler usw. ähnlich

sieht nicht viel anders aus als JTextField/ JButton an sich?
richtig, dafür sind es deine eigenen Klassen und die können ein gemeinsames Interface JCompHandler mit einheitlicher Methode getText() implementieren,
später interessiert dich gar nicht, welche Subklasse es genau ist, einfach die gemeinsame Methode aufrufen
 

StefanTmp

Mitglied
Naja gut, aber im ctor muss ich ja dann trotzdem mit instanceof prüfen, um welches übergebenes Objekt es sich handelt, oder nicht?

Grüße
StefanTmp
 
Zuletzt bearbeitet:

HannsW

Bekanntes Mitglied
Naja gut, aber im ctor muss ich ja dann trotzdem mit instanceof prüfen, um welches übergebenes Objekt es sich handelt, oder nicht?

Grüße
StefanTmp

als interessierter Mitleser: was ist "ctor" ?
Hanns

Nachtrag: wenn man den Subklassen ne "int" als Ident mitgibt, könnte man auch nen Switch verwenden ( ich hab nämlich ein ähnliches Problem !)
 
B

bygones

Gast
ctor = constructor

was spricht gegen das allgemeine interface ?
 
S

SlaterB

Gast
@StefanTmp
du kannst doch nicht 10 Minuten später in ein bekanntes Post noch eine Frage hineineditieren,
die habe ich natürlich überlesen,

schließe mich dann HannsW an ;)

edit: mehrere Konstruktoren, pro Typ einen
 

StefanTmp

Mitglied
Achso, dass dann mit Autoboxing (nennt man das so?) des richtige Member zugewiesen wird usw..?
sorry für den edit-Mist!

Grüße
StefanTmp
 

StefanTmp

Mitglied
Problem ist, dass wir auf 4GL Seite nicht objektorientiert sind, d.h. wir rufen Konstruktoren in der 4GL in der Art auf:

lButtonHandle=createButton(...);

Wir müssen also auf Java-Seite die statischen Methoden createButton(..) zur Verfügung stellen. Wenn ich das mit dem allgemeinen Interface richtig verstanden habe
(Erklärung:
Ein Interface a´la TextBearbeiten, in der Methoden wie getText(), setText(String).. vorhanden sind. Dieses Interface wird dann von den eigentlichen Klassen 4GLButton, 4GLTextField.. implementiert. Damit stehen allen 4GL Elementen die Methoden aus der TextBearbeiten zur Verfügung. )

hilft das in unserem Fall aber nicht viel, da man in einem Interface meines Wissens nach keine statischen Methodenköpfe deklarieren kann.

Gruß
StefanTmp
 
S

Spacerat

Gast
Quick and Dirty to Copy and Paste
Java:
static public String getText(String pComponentId)
{
  try {
    Method m = mMap.get(pComponentId).getMObject().getClass().getMethod("getText");
    return m.invoke(comp).toString();
  } catch(Throwable e) {
    return "";
  }
}
Diese Methode ist so evilig, dass sie rigoros alle Fehler einfach verschluckt und in diesem Fall einen Leerstring liefert.
1. pComponentId darf null sein
2. die in der Map gespeicherte Component muss keine öffentliche getText()-Methode haben
3. getText() darf andere Objekte ausser String zurückgeben.
 
B

bygones

Gast
Problem ist, dass wir auf 4GL Seite nicht objektorientiert sind, d.h. wir rufen Konstruktoren in der 4GL in der Art auf:

lButtonHandle=createButton(...);

Wir müssen also auf Java-Seite die statischen Methoden createButton(..) zur Verfügung stellen. Wenn ich das mit dem allgemeinen Interface richtig verstanden habe
(Erklärung:
Ein Interface a´la TextBearbeiten, in der Methoden wie getText(), setText(String).. vorhanden sind. Dieses Interface wird dann von den eigentlichen Klassen 4GLButton, 4GLTextField.. implementiert. Damit stehen allen 4GL Elementen die Methoden aus der TextBearbeiten zur Verfügung. )

hilft das in unserem Fall aber nicht viel, da man in einem Interface meines Wissens nach keine statischen Methodenköpfe deklarieren kann.

Gruß
StefanTmp
das versteh ich nicht wirklich... was auch immer ihr habt und wie ihr euch das erzeugt... zurueckgeben koennt ihr immer ein gemeinsames interface welche die methoden hat die gebraucht sind ?!
 

HannsW

Bekanntes Mitglied
Quick and Dirty to Copy and Paste
Java:
static public String getText(String pComponentId)
{
  try {
    Method m = mMap.get(pComponentId).getMObject().getClass().getMethod("getText");
    return m.invoke(comp).toString();
  } catch(Throwable e) {
    return "";
  }
}

Wo müsste denn dieser Code hin?
Mir schwirrt der Kopf
 
S

Spacerat

Gast
am besten nirgendswohin... wie spacerat selbst schreibt... quick & dirty - im Sinne von - nicht machen
Ganz deiner Meinung. Die Lösung mit dem Interface ist und bleibt die beste.
...ansonsten ersetzt es die "getText()"-Methode des TS.
BTW: Was ist eigentlich dieses 4GL? Ich hab' da nur so 'ne Verallgemeinerung gefunden: 4th Grade Language. Mit so etwas kann ich ja überhaupt nichts anfangen.
 

HannsW

Bekanntes Mitglied
Ganz deiner Meinung. Die Lösung mit dem Interface ist und bleibt die beste.

WIe würde denn das aussehen?

Ich schreibe ein Interface XY :
Java:
public interface XY{
   public String getText(){
          return ( myName == null ? "" : meinName ) ;
  }
}[/Java]
Dann schreibe ich mir classe wie z.b MyJTextField etc und implementiere diese interface,
und deklariere String myName = "irgendwas".

Und kann dann in der klasse mit den vielen "instanceof"  durch "object".getName() auf den Typ folgern? 

bzw, wenn ich es mit int machte so etwas schreiben?
[code=Java]
public interface XY{
   public String getIdent(){
          return ( myIdent == null ? -1 : ident ) ;
  }
}

  //......andere klasse
		Component[] children = thePanel.getComponents();
		for (int n = 0; n < children.length; n++) {
                        switch (children[n].getIdent()) {
			case D_JTEXTFIELD:
                                System.out.println("ich bin ein JTextField");		
                                break;
                        case ....

			default:
				break;
			}

????
 

Michael...

Top Contributor
Ich schreibe ein Interface XY :
Java:
public interface XY{
   public String getText(){
          return ( myName == null ? "" : meinName ) ;
  }
}[/Java][/QUOTE]
In einem Interface kann man nur den Methoden-Kopf beschreiben. Dein Interface enthält aber eine konkrete Implementierung.

Mit einem gemeinsamen Interface könnte das ganze so ausschauen:
[code=Java]import java.util.*;

public class InterfaceDemo {
	public static void main(String[] args) {
		ArrayList<Object> list = new ArrayList<Object>();
		list.add(new MyObject("Hello"));
		list.add("Stringobject");
		list.add(MyObject.createMyObject("Hola"));
		list.add(new MyObject2("Bye"));
		for (int i=0; i<list.size(); i++) {
			Object o = list.get(i);
			if (o instanceof MyInterface)
				System.out.println(((MyInterface)o).getText());
			else
				System.out.println(o.getClass().getName() + " is not an instance of MyInterface");
		}
	}

}

class MyObject implements MyInterface {
	private String text;
	
	public MyObject(String text) {
		this.text = text;
	}
	
	public static MyObject createMyObject(String text) {
		return new MyObject(text);
	}
	
	public String getText() {
		return "I'm an instance of " + this.getClass().getName() + ". And my text is: " + text;
	}
}

class MyObject2 implements MyInterface {
	private String text;
	
	public MyObject2(String text) {
		this.text = text;
	}
	public String getText() {
		return "I'm an instance of " + this.getClass().getName() + ". And my text is: " + text;
	}
}

interface MyInterface {
	public String getText();
}

Wenn man in die Liste nur Objekte einfügen will, die MyInterface implementieren, kann man diese auch so initialisieren:
Code:
ArrayList<MyInterface> list;
Dann muss man später auch nicht casten.
 
S

Spacerat

Gast
Das Interface
Java:
public interface TextComponent
{
  String getText();
}
MyJTextField
Java:
public class MyJTextField
extends JTextField
implements TextComponent
{
  public MyJTextField()
  {
    super();
  }

  public String getText()
  {
    super.getText();
  }
}
MyJButton
Java:
public class MyJButton
extends JButton
implements TextComponent
{
  public MyJButton()
  {
    super();
  }

  public String getText()
  {
    super.getText();
  }
}
"getText()"-Methode
Java:
static public String getText(String pComponentId)
{
  Object o = mMap.get(pComponentId).getMObject();
  if(o instanceof TextComponent) {
    return ((TextComponent) o).getText();
  }
  return ";
}
Schmeisst NullPointerException, wenn pComponentID nicht in der Map ist.
Gibt Leerstring zurück, wenn das gefundene Objekt nicht TextComponent implementiert.
 
B

bygones

Gast
interfaces implementieren keine methode...

zb
Java:
public interface TheInterface {
    public String getText();
}

die Klassen die nun erstellt werden muessen das Interface implementieren:
Java:
public class AComponent implements TheInterface {
   public String getText() {
      return "einString";
   }
}

public class XComponent implements TheInterface {
   public String getText() {
      return "einStringWasAnderes";
   }
}
im code nun selber kann man dann zb haben
Java:
TheInterface anObject = getObject() ;
String text = anObject.getText();

wobei getObject dann ein konkretest Objekt erstellt (also AComponent oder XComponent).

Wie gesagt - das ist zwar die sauberste Loesung, aber setzt vorraus, dass man die Moeglichkeit hat ein solches Konstrukt drumrumzubauen
 
B

bygones

Gast
Java:
static public String getText(String pComponentId)
{
  Object o = mMap.get(pComponentId).getMObject();
  if(o instanceof TextComponent) {
    return ((TextComponent) o).getText();
  }
  return ";
}
ah nutze doch das interface dass du erstellt hast...

Java:
static public String getText(String pComponentId)
{
  return mMap.get(pComponentId).getMObject().getText();
}
problematik der moeglich NPE bleibt natuerlicyh
 
S

Spacerat

Gast
...und zusätzlich die Möglichkeit einer ClassCastException, wenn in der Map auch noch andere Objekte als TextComponents sind und gerade die gefundene TextComponent nicht implementiert.
 

StefanTmp

Mitglied
Hallo,

erstmal sorry, hatte die letzten Tage einiges um die Ohren, bin also nicht zum Antworten gekommen.
Das Problem hat sich mittlerweile gelöst, da wir die Spezifikation in unserer 4GL geändert haben.
Danke nochmal für die Posts.

Grüße
StefanTmp
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
O Funktioniert dies? Und gibt es eine bessere Lösung? Java Basics - Anfänger-Themen 6
S Bessere Lösung? Java Basics - Anfänger-Themen 4
S LineNumberReader - bessere Lösung möglich? - Log4J Java Basics - Anfänger-Themen 9
G Bessere Lösung für SQL STMNT ? (Schneller?) Java Basics - Anfänger-Themen 4
T KLasse das bessere Array Java Basics - Anfänger-Themen 16
M Bessere bzw. kürzere Variante für Code? Java Basics - Anfänger-Themen 2
cyro Best Practice Bessere Alterative zu ArrayList gesucht Java Basics - Anfänger-Themen 3
N Bessere Performance durch final: wann denn überhaupt? Java Basics - Anfänger-Themen 28
F bräuchte eine bessere entwicklungsumgebung Java Basics - Anfänger-Themen 2
S unschöne schleifen.jemand ne bessere idee Java Basics - Anfänger-Themen 4
J Wartezustand in Endlosschleife - bessere Alternativen Java Basics - Anfänger-Themen 20
G was ist die bessere Variante Java Basics - Anfänger-Themen 4
C Rechnen mit Brüchen, ist meine Lösung soweit richtig? Java Basics - Anfänger-Themen 4
N Ich kriege ganze zeit die Fehlermeldung "Inhalt der Zwischenablage kann nicht in die ausgewählten Elemente eingefügt werden" hat jemand eine Lösung? Java Basics - Anfänger-Themen 6
W Texteingabe - Bedeutung Fehlermeldung, Lösung? Java Basics - Anfänger-Themen 18
M Kennt jemand die richtige Lösung? Java Basics - Anfänger-Themen 7
H Codewars akzeptiert Lösung nicht Java Basics - Anfänger-Themen 29
A Selbe Aufgaben stellung, andere Lösung Java Basics - Anfänger-Themen 7
M Lösung Aufgabe - Java Programmiren lernen für Dummies Java Basics - Anfänger-Themen 11
ZH1896ZH Java-SemesterTest ohne Lösung :( Java Basics - Anfänger-Themen 47
D Beim Programmieren auf die Logisch einfache Lösung kommen. Java Basics - Anfänger-Themen 17
M Hamstersimulator- lösung hilfe benotigt Java Basics - Anfänger-Themen 3
M Hamstersimulator- Lösung? Java Basics - Anfänger-Themen 3
E Mathematische Aufgabe: Antwort entspricht nicht der Lösung Java Basics - Anfänger-Themen 5
W Tipps/Anmerkungen zu meiner Lösung?! Java Basics - Anfänger-Themen 2
H lösung aufgabe Java Basics - Anfänger-Themen 12
J Gleiche Methode in 2 verschiedenen Klassen - Lösung ? Java Basics - Anfänger-Themen 8
P java.lang.ClassCastException Bedeutung und Lösung Java Basics - Anfänger-Themen 3
M Methoden Fehler und finde die Lösung nicht wirklich Java Basics - Anfänger-Themen 6
J RPN Taschenrechner - keine Lösung!! Java Basics - Anfänger-Themen 84
I java.lang.ArrayIndexOutOfBoundsException at lösung.main Java Basics - Anfänger-Themen 3
J Best Practice DOS Fenster mit Befehlszeile (Lösung) Java Basics - Anfänger-Themen 2
S mehrfache if-Abfragen - beste Lösung Java Basics - Anfänger-Themen 1
J Einfache pub/sub Lösung mit ausführlicher Doku Java Basics - Anfänger-Themen 5
D Best Practice Testdaten. Was ist eine saubere Lösung? Java Basics - Anfänger-Themen 3
D Datentypen Datentyperstellung | Kompiler sagt Syntax Error doch ich find keine Lösung Java Basics - Anfänger-Themen 2
V Verstehe die Lösung einer Aufgabe von Grunkurs-Java nicht. Java Basics - Anfänger-Themen 11
P Verstehe Lösung einer Aufgabe von "Grundkurs-Java" nicht Java Basics - Anfänger-Themen 5
E Brauche eine Antwort zum Thema RegEx ( Alternative zur Lösung auch gesucht ) Java Basics - Anfänger-Themen 5
C Lösung für RegEx in Java gesucht Java Basics - Anfänger-Themen 2
S Eine rekursive Lösung Java Basics - Anfänger-Themen 4
G OOP [Eilig] Biete 10€ für Lösung von 2 Grundlagen-Aufgaben Java Basics - Anfänger-Themen 6
C For-Schleife wie kommt man auf die Lösung? Java Basics - Anfänger-Themen 2
M Erste Schritte boolean: ist Zahl Hexadezimal - Lösung verwirrend Java Basics - Anfänger-Themen 6
C Best Practice Was ist die elegantere Lösung bzgl. Klassenaufteilung in Robocode ? Java Basics - Anfänger-Themen 3
G Vererbung Lösung Standardproblem Java Basics - Anfänger-Themen 2
J Lösung eines Zahlenintervall wierd an der Falschen Stelle angezeigt. Java Basics - Anfänger-Themen 8
C Sortierverfahren - allgemeine Lösung? Java Basics - Anfänger-Themen 9
3 Bitte um Hilfe bei Lösung einer Aufgabe Java Basics - Anfänger-Themen 16
D speicherschonendere lösung? Java Basics - Anfänger-Themen 19
M Interval Teilmenge bestimmen - Fehler in meiner Lösung Java Basics - Anfänger-Themen 6
M Suche Korrektor für meine Lösung (FH: Java1 - Übungsklausur) Java Basics - Anfänger-Themen 4
F OOP Wieder mal Zugriffsprobleme... (Lösung am Ende) Java Basics - Anfänger-Themen 11
U JTable viele möglichkeiten, keine Lösung Java Basics - Anfänger-Themen 5
T Objektübergabe - saubere Lösung? Java Basics - Anfänger-Themen 3
U Rekursive lösung von pascal dreieck Java Basics - Anfänger-Themen 11
A brauche eine Lösung für Problem bei Moorhuhn-Version Java Basics - Anfänger-Themen 5
C Lösung einer Aufgabe mittels Iteration und Rekursion Java Basics - Anfänger-Themen 12
F Eingabe darf nur 1 oder 0 sein. Meine Lösung macht Probleme. Java Basics - Anfänger-Themen 8
C Frage zu try - catch (saubere Lösung?) Java Basics - Anfänger-Themen 3
D Benutzung von globalen Variablen einzigste Lösung? Java Basics - Anfänger-Themen 6
F Servlets, Formulare und ich weiß keine Lösung Java Basics - Anfänger-Themen 4
A Struktur -> Beste Lösung? Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben