Typecast entfernen

J

JohannisderKaeufer

Gast
Ich habe folgendes Programm

2 Klassen
Java:
/** Abstrakte Klasse */
class AbstractClass {
  void m1(){}
}
/** Erweiterung der Abstrakten Klasse */
class ConcreteClass extends AbstractClass {
  void m2(){}
}

2 weitere Klassen, die Methoden der ersten beiden Klassen aufrufen
Java:
/** Ruft m1 auf */
class Caller1 implements Caller{
  void call(AbstractClass c){
    c.m1();
  }
}
/** Ruft m2 auf */
class Caller2 implements Caller{
  void call(AbstractClass c){
    ConcreteClass cc = (ConcreteClass) c;
    cc.m2();
  }
}

und eine Klasse die das ganze Zusammenhalten soll und in der Methode foo, die entsprechenden Methoden aufruft.
Java:
class Main{
  List<Caller> callers;
  AbstractClass c;
  public Main(List<Caller> caller, AbstractClass c){
    this.caller = caller;
    this.c = c;
  }

  void foo(){
    for(Caller caller : callers){
      caller.call(c);
    }
  }
}

Soweit so gut. Das funktioniert auch, wenn ich in der Main Methode so zusammenbaue.

Java:
public static void main(String[] args){
  List<Caller> callers = new ArrayList<Caller>();
  callers.add(new Caller1();
  callers.add(new Caller2();
  AbstractClass ac = new ConcreteClass();
  new Main(callers, ac);
}


Wenn ich allerdings in der Main-Methode eine AbstractClass initialisiere, dann läuft das ganze solange bis ich in der Klasse Caller2 den Typecast auf ConcreteClass durchführe. Und deshalb würde ich gerne den Typecast umgehen, sodaß ich möglichst schon zur Compilezeit diesen Fehler erhalte.

Und genau hier happert es momentan. Ich hab mir schon ein paar Sachen mit Generics überlegt, die aber irgendwie alle nicht hinhauen. Vielleicht hat noch jemand eine Idee oder einen Beweis das das nicht geht.

Edit: Ok, ich hab noch was vergessen.
Das Programm soll zuerst mit den Klassen Main, Caller1 und AbstractClass zusammenarbeiten und dann dynamisch erweitert werden können durch die Klassen Caller2 und entsprechend ConcreteClass ohne wieder an Main, Caller1 oder AbstractClass handanzulegen.

Idealierweise stelle ich mir eine Signatur für den Konstruktor von Main so oder zumindest soähnlich vor
Java:
callers = new ArrayList<Caller<ConcreteClass>>();
new Main<ConcreteClass>(callers, new ConcreteClass);
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Wie schaut denn das Interface Caller aus? Schreibt das die Methode call vor?
Das Problem an deinem Konstrukt ist, dass du in der Methode eine AbstractClass erwartest, intern dann aber mit ner ConcreteClass arbeiten willst/musst.

Wäre folgendes nicht machbar für dich?

Java:
public interface Caller<T> {
  public void call (T t);
}
 
J

JohannisderKaeufer

Gast
Java:
public interface Caller<T> {
  public void call (T t);
}

Sowas hatte ich probiert, aber irgendwie hing es dann. Jetzt hab ich es aber raus denke ich.

Das Interface:
Java:
public interface Caller<T extends AbstractClass>{
  void call(T t);
}

Probleme hatte ich bisher bei deren Implementierung. Nun habe ich es so gemacht
Java:
class Caller1<T extends AbstractClass> implements Caller<T>{
  void call(T t){ 
    t.m1();
  }
}

class Caller2<T extends ConcreteClass> implements Caller<T>{
  void call(T t){ 
    t.m2();
  }
}

Und die Main Klasse
Java:
class Main<T extends AbstractClass>{
  List<Caller<T>> callers;
  T c;
  public Main(List<Caller<T>> caller, T c){
    this.caller = caller;
    this.c = c;
  }
 
  void foo(){
    for(Caller<T> caller : callers){
      caller.call(c);
    }
  }
}

Jetzt ist es perfekt, wenn ich versuche was zu "brechen", dann hagelt es entweder Exceptions oder zumindest Warnings.
 
S

so0jvpwemm

Gast
Irgendwie schaut das ganze Konstrukt recht merkwürdig aus? Wird die m1() an der konkreten Klasse auch irgendwann man aufgerufen? Warum der Caller?
 
J

JohannisderKaeufer

Gast
Irgendwie schaut das ganze Konstrukt recht merkwürdig aus?

Gut ich habe hier das ganze auf das notwendigste reduziert. Dort wo ich das ganze einbauen möchte macht es allerdings schon Sinn. Es ist hier ein wenig aus dem Context gerissen.

Wird die m1() an der konkreten Klasse auch irgendwann man aufgerufen?

Ja, die Implementierung wird aber von der AbstractClass geerbt, von daher paßt das schon.

Warum der Caller?

Tatsächlich ist da noch etwas mehr dahinter. In der Methode foo() werden nachher nicht alle Caller nacheinander aufgerufen sondern ein passender gesucht der dann die entsprechende Methode aufrufen soll.

Ein Teil des Programms (Main) kümmert sich nachher, welche Methoden aufgerufen werden können und sollen der andere Teil stellt die Methoden (AbstractClass und ConcreteClass) zur Verfügung.

Die Caller repräsentieren eine Methode die aufgerufen werden kann. Und mit den einzelnen Callern, kann ich Zentral (in der main-Methode) steuern welche Methoden zur Verfügung stehen. (z.B. haben Admins gegenüber normalen Usern mehr Möglichkeiten zur Verfügung)

Die Geschichte mit AbstractClass und ConcreteClass, kann man sich so vorstellen, daß ein Teil eine Grundfunktionalität zur Verfügung stellt und ein weiterer diese erweitert. (z.B. Basisdienst und Premiumdienst)

Oder einfach DependencyInjection ohne Framework.
 
I

Interfaces

Gast
In meinen Augen macht das alles immer noch keinen Sinn.

Du hast ein Interface "Caller" und in diesem die Methode "void call(AbstractClass)" definiert.
Dieses Interface implementieren die Klasse "Caller1" und "Caller2".
Zusätzlich die abstrakte Klasse "AbstractClass" die die Methode "void m1()" definiert.
Der einzige Unterschied zwischen dem Interface "Caller" und der abstrakten Klasse "AbstractClass" ist das das Interface die implementierende Klasse dazu zwingt die vorgegebene Methode zu implementieren. Deine "AbstractClass" macht dies nicht da die Methode selbst nicht als "abstract" deklariert ist.
Nun willst du einen List-Iterator bauen der über alle registrierten "Caller" geht und dabei ein Objekt von "AbstractClass" übergibt. Wenn allerdings das Objekt eine Instanz von "ConcreteClass" ist soll im entsprechenden "Caller" in "void call(AbstractClass" anstatt "void m1()" von "AbstractClass" eher "void m2()" von "ConcreteClass" gecallt werden.
Und damit das geht brauchst du natürlich einen Cast den du jetzt mit Generics weghaben willst.

Ganz erlich : WAS SOLL DER MIST ?
Das hat weder Sinn noch passt es irgendwie zu den von dir verwendeten Konzepten. Generell finde ich es schon krass Interfaces, abstrakte Klassen und dann noch Generics so krass zu mischen.

Das einfachste wäre gewesen wenn du in "AbstractClass" die Methode "void m1()" ebenfalls als "abstract" deklariert und dann in "ConcreteClass" mit
Java:
void m1() { m2(); }
implementiert hättest.
Schnell, einfach, sauber und vor allem verständlich.

Mag sein das das ganze so ohne den Kontext wenig Sinn ergibt, aber wenn deine Frage nun mal auf einen bestimmten Kontext bezogen ist solltest du diesen mal mitposten oder ein KSKB basteln an dem man das Problem auch versteht und erkennt was du am Ende damit anstellen willst. Stattdessen postest du hier etwas an sich sinnloses weil es aus dem Zusammenhang gerissen wurde.

Fass den Post nicht "aggressive" auf *wobei eher schon ein negativer Konstruktivbeitrag sein soll* aber so kann man dir nun mal bei diesem speziellen Problem schlecht helfen. Und es ist nicht verwunderlich warum einige sowas posten wie : "sieht schräg aus". Vielleicht gibt es ja eine viel bessere Lösung. Aber die können wir schlecht erraten ohne wichtige Infos. Denn erlich : das "Teil" da ist so wie es da steht echt ziemlich schräg und würde so sicher niemand verwenden.
 
S

Spacerat

Gast
Wieso denn immer alles so abstract? Ist eine Adapterklasse evtl. auch ein Designpattern?
Java:
interface ToAdapt {
	void m1();
	void m2();
}

class AdapterClass implements ToAdapt {
	void m1() {
	}
	void m2() {
	}
}

class ConcreteClass extends AdapterClass {
	void m2() {
		
	}
}
ConcreteClass überschreibt nun wahlweise m1 und/oder m2, dann den Typecast auf ToAdapt und gut is'. Für weitere Inspirationen schaust du dir evtl. mal die Listenerinterfaces des AWT an.
 
Zuletzt bearbeitet von einem Moderator:
J

JohannisderKaeufer

Gast
Abstract war jetzt etwas ungünstig gewählt.

Ich möchte am Ende mehrere Anwendungen erstellen.
Eine sieht so aus
Java:
interface BasisI{
  void macheBasisZeug();
}
interface ErweiterungAI{
  void macheAZeug();
}
interface AnwendungA extends BasisI, ErweiterungAI{}

und eine beispielsweise so

Java:
interface BasisI{
  void macheBasisZeug();
}
interface ErweiterungB{
  void macheBZeug();
}
interface ErweiterungC{
  void macheCZeug();
}
interface AnwendungBC extends BasisI, ErweiterungB, ErweiterungC{}

Also bei der zweiten Komplett ohne dem A-Zeug.
Letztendlich habe ich einmal eine Anwendung
Code:
BasisI basis = new AnwendungA(){};
Und einmal
Code:
BasisI basis = new AnwendungBC(){};

Hier liegt allerdings nicht das Problem! Dies bläht nur die Beschreibung auf und läßt sich im prinzip auf
eine AbstractClass und ConcreteClass extends AbstractClass runterkochen.
Ich wiederhole es nochmals "ich möchte am Schluß mehrere Anwendungen haben".
Diesen Bereich könnte man auch Backend betitteln. Das stellt die Funktionalität bereit.

Jetzt kommt die Verknüpfung mit dem UserInterface.
Das Userinterface soll immer ähnlich aussehen und jeweils die Funktionen bereitstellen, die auch im Backend zur Verfügung stehen.
Jetzt kommen diese ominösen Caller ins Spiel.
Ein Caller soll eine bestimmte Funktion im Backend aufrufen können.
Das hat zur Folge das das Backend auch diese Funktion bereitstellen muß.
Der User bekommt schließlich die Auswahl einen Caller auszuwählen um eine Funktion im Backend aufzurufen.
Das führt dann z.B. zu
Code:
caller.callOn(backend);

Also zurück zum Anfang des UI.
Ich möchte nur einmal ein UI schreiben!
Das UI bekommt ein Backend übergeben und hält darauf eine Referenz.
Das UI bekommt eine Liste von möglichen Funktionsaufrufen, hier caller genannt übergeben.
Das UI weiß wie es die einzelnen Caller darstellen und Aufrufen kann.

Jetzt muß ich einen Typ für das Backend angeben.
Zur Auswahl stehen Object und BasisI. Object fällt weg, da UI noch ein paar anderer Dinge aus BasisI direkt abfragt.

Halte im UI für das Backend als Typ BasisI.
Dann kann ich den Callern nur ein BasisI übergeben und die caller müßen dann eigenständig einen Typcast durchführen. Folgen wären ClasscastExceptions zur Laufzeit. Dies sollte aber vermeidbar sein!

Also Generics! damit kann ich im UI bestimmen das das Backend vom Typ <T extends BasisI> ist. Für jeden Caller kann ich einzeln bestimmen was im Backend zur Verfügung stehen muß
Code:
Caller<T extends ErweiterungA>
und somit
Code:
void call<T>()

Wenn ich nun das ganze Initialisiere Bekommt das UI den Typ AnwendungA. Somit akzeptiert das UI nur ein Backend vom Typ AnwendungA und die Liste von Callern kann ich ebenfalls auf AnwendungA typen.

Für die AnwendungBC das ganze mit AnwendungBC typen.

Versuche ich nun für AnwendungBC einen Caller der ErweiterungA benötigt hinzuzufügen, dann bekomme ich wenn ich nicht typisiere eine Warning und wenn ich typisiere einen Error.

Wenn ich nun im weiteren weitere Erweiterungen schreibe, dann brauche ich einen Caller, den ich zentral dem UI hinzufügen kann und eine entsprechende Erweiterung für das Backend.

Es muß auch gesagt werden, daß ein Caller nicht nur die Funktion für das Backend aufruft, sondern auch Daten einliest, Convertierungen vornimmt und parameter für den Funktionsaufruf im Backend setzt.
Eine Erweiterung im Backend besteht auch aus mehreren Funktionen, wobei ein Caller sich nur um jeweils eine dieser kümmern wird.

TL;DR
Stell dir ein JFrame vor dem du nur ein Model und beliebige ActionListener übergeben mußt die Methoden auf dem Model aufrufen. Stell dir auch noch vor, daß dieses JFrame für jeden ActionListener einen Button mit entsprechender Beschriftung erstellt und dem UI hinzufügt. Und jetzt stell dir vor, daß soll noch lose gekoppelt, dynamisch kombinierbar und Typesafe sein.

Funktioniert jetzt aber schon, daher erledigt
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Klassen Typecast unnötig? Allgemeine Java-Themen 2
D Datentypen Unklarheit bei Typecast / arithm. Überlauf Allgemeine Java-Themen 2
M typecast error Allgemeine Java-Themen 14
Q Typecast zwischen Klassen mit implementierter Schnittstelle Allgemeine Java-Themen 4
I strip-debug - debug-Infos aus mitgelieferter Lib entfernen Allgemeine Java-Themen 3
E Hall vom Clip entfernen Allgemeine Java-Themen 5
OnDemand Teile eines Links entfernen Allgemeine Java-Themen 6
TheSepp Wie kann man Leerzeichen aus einer Array liste entfernen? Allgemeine Java-Themen 10
killig Textdatei einlesen und in HashMap speichern (duplikate entfernen) Allgemeine Java-Themen 12
J Spieler aus der Spielerliste zu entfernen Allgemeine Java-Themen 0
J Spieler aus der Spielerliste entfernen in dem Spiel 17und 4 Allgemeine Java-Themen 2
C Koordinaten LONG/LAT eines neuen Punktes in bestimmter Entfernen und Winkel berechnen Allgemeine Java-Themen 3
Kingamadeus2000 Alle mehrfach vorkommenden Buchstaben rekursiv aus einem String entfernen. Allgemeine Java-Themen 6
R char aus String entfernen Allgemeine Java-Themen 10
J Wie kann ich von Vornherrein einen Fokus auf ein Objekt entfernen? Allgemeine Java-Themen 3
Y ArrayListe eingegebenen index entfernen Allgemeine Java-Themen 1
S Inlining erzwingen kombiniert mit Entfernen von Imports..? Allgemeine Java-Themen 11
G JFileChooser Fokus entfernen?! Allgemeine Java-Themen 15
Neumi5694 Compiler-Fehler Konstanten entfernen während des Kompiliervorgangs Allgemeine Java-Themen 7
S Methoden "Unschöne" Break-Anweisung aus verschachtelter Funktion entfernen Allgemeine Java-Themen 11
KeVoZ_ JSoup - HTML Tag entfernen Allgemeine Java-Themen 1
mrBrown Unicode-WhiteSpaces aus String entfernen Allgemeine Java-Themen 14
S Abhaengigkeiten auf Klassenebene entfernen..? Allgemeine Java-Themen 7
T ArrayList zeilenumbruch entfernen Allgemeine Java-Themen 13
J Pattern aus String entfernen Allgemeine Java-Themen 2
R Duplikate aus einer Textdatei entfernen? Allgemeine Java-Themen 20
K Input/Output störende Leerzeichen entfernen Allgemeine Java-Themen 11
S Entfernen von allen Nicht-Buchstaben chars aus einem String ohne Regex..? Allgemeine Java-Themen 10
T Hardware sicher entfernen Allgemeine Java-Themen 8
M Mehrere CRLF entfernen Allgemeine Java-Themen 13
Q "Doppelte" Einträge einer Liste entfernen Allgemeine Java-Themen 14
T Swing JTextAera Zeilenumbruch entfernen Allgemeine Java-Themen 7
X Chinesische Schriftzeichen aus String entfernen Allgemeine Java-Themen 6
T JRE komplett von einem PC entfernen? Allgemeine Java-Themen 5
J Schlüsselwörter entfernen - Wo / wie am performantesten? Allgemeine Java-Themen 3
M Klasse aus xyz.class Datei laden / package entfernen? Allgemeine Java-Themen 4
L-ectron-X Regex zum Entfernen von mehrzeiligen Kommentaren Allgemeine Java-Themen 2
E Html tags entfernen optimieren Allgemeine Java-Themen 12
G Element aus Liste entfernen Allgemeine Java-Themen 6
X Duplikate aus eigenen Datentypen entfernen Allgemeine Java-Themen 14
C Zeilenumbruch aus JTextArea entfernen Allgemeine Java-Themen 6
T Element aus Vector entfernen Allgemeine Java-Themen 4
G Mit JarSigner erstellte Signierung entfernen Allgemeine Java-Themen 8
hdi text durchsuchen -> satzzeichen entfernen Allgemeine Java-Themen 5
C Satzzeichen aus String entfernen Allgemeine Java-Themen 6
S Anonymen MouseListener entfernen? Allgemeine Java-Themen 2
R Entfernen der '..' Notation aus dem Pfad Allgemeine Java-Themen 2
G führende nullen entfernen Allgemeine Java-Themen 14
A ArrayListe :Doppelte entfernen -> keine Referenzen Allgemeine Java-Themen 26
A Leerzeichen entfernen Allgemeine Java-Themen 3
G HTML Code aus String mittels REGEX entfernen Allgemeine Java-Themen 2
L Whitespace in einer html Site entfernen Allgemeine Java-Themen 10
M Elemente aus Liste entfernen? Allgemeine Java-Themen 7
T Duplikate aus ArrayList entfernen Allgemeine Java-Themen 2
G zeilenummern entfernen Allgemeine Java-Themen 9
G Hashset einen eintrag zufällig entfernen Allgemeine Java-Themen 4
B Entfernen von Zeilen/Spalten aus einer Matrix Allgemeine Java-Themen 8
T - Zeilenumbruch entfernen Allgemeine Java-Themen 2
byte Erste Zeile einer Textdatei entfernen Allgemeine Java-Themen 5
J sonderzeichen entfernen Allgemeine Java-Themen 6
m@nu Schreibschutz entfernen und OutputStream öffnen Allgemeine Java-Themen 6
G Leerzeichen entfernen unter 1.3.x Allgemeine Java-Themen 5
C GC: Referenz entfernen Allgemeine Java-Themen 6
F Dateigröße eines entfernen Images ermitteln Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben