Verschiedene Versionen eines Interfaces

Status
Nicht offen für weitere Antworten.

Lim_Dul

Top Contributor
Mir spukt gerade folgende Frage im Kopf rum, ist momentan eher theorethische Natur, weil ich das Problem vermeiden will. Aber interessieren würde mich es dennoch mal.

Gegeben seien von einem Interface A zwei Versionen. (Die eine älter, die eine neue) sowie zwei davon abgeleitete Klassen.

Code:
// Version 1
public interface A {
  public void doSomething();
}

Code:
// Version 2, neuer

public interface A {
  public void doSomething();
  public void doSomeOtherThing();
}

Klasse B1 wurde mit der Version 1 kompiliert, Klasse B2 mit der Version 2.

Wann kracht es, wenn ich sowohl ein Objekt von B1 und B2 anlege? Sofort beim laden der Klasse B1? Oder erst wenn ich auf einem Objekt der Klasse B1 die Methode doSomeOtherThing() versuche aufzurufen?


Hintergrund der ganzen Geschichte ist der, dass ich für mein Programm eine Art Plugin Struktur haben will für Computergegner. Dabei kann es sein, dass sich das zu implementierende Interface erweitert, wenn neue Optionen hinzukommen. Ich kann allerdings garantieren, dass die neuen Methoden niemals bei alten Versionen aufgerufen werden.

Allerdings denke ich momentan nach, wie ich das sauberer lösen kann, dennoch würde mich eine Antwort interessieren.
 

byte

Top Contributor
Also wenn Du wirklich beide Varianten des Interfaces gleichzeitig benutzen willst, dann kommt es doch darauf an, in welchem Package sie sich befinden. Sind die qualifizierten Namen der Interfaces also unterschiedlich, dann wirds keine Probleme geben (hängt dann halt vom Import Statement ab). Der andere Fall, also zweimal der gleiche qualifizierte Name, das würde ja nur gehen, wenn die Dateien aus unterschiedlichen Jars stammen. Dann wirds wohl zu nem Compiler Fehler kommen. Ausprobiert habe ich sowas aber noch nie.
 

nocxsville

Bekanntes Mitglied
Hi diese Java Schwachstelle ist mir auch schon aufgefallen. Es kracht sobald du versuchst b1.doSomeOtherThing() aufzurufen.

Gruß,
nocxsville
 
B

Beni

Gast
Es kracht mit einer "NoSuchMethodException", die kann man wenigstens abfangen.
 
G

Gast

Gast
die richtige vorgehensweise wäre das neue interface von a abzuleiten sprich:

public interface Aneu extends A {
public void doSomeOtherThing();
}

dann weiß man auch zu jedem Zeitpunkt welches Interface gerade verwendet wird
 

Lim_Dul

Top Contributor
Gast hat gesagt.:
die richtige vorgehensweise wäre das neue interface von a abzuleiten sprich:

public interface Aneu extends A {
public void doSomeOtherThing();
}

dann weiß man auch zu jedem Zeitpunkt welches Interface gerade verwendet wird

Ideal wäre es, sowas überhaupt zu vermeiden ;)

Dieser Vorschlag hätte wieder den Nachteil, dass ich irgendwann eine riesige Kaskade von Interfaces habe A, A1, A2, ... An und das Testen, welche Version das zu ladende Plugin implementiert, in eine if instanceof Kaskade ausartet. Auch nicht schön :)

Wenn ich "einfach" das Interface ändere und gleichzeitig relativ sicher garantierten kann, dass bei alten Plugins die neuen Methoden nie aufgerufen werden, habe ich weniger Arbeit. Und zur Sicherheit kann ich jede Methode immer noch in ein try - catch packen und entsprechend im Fehlerfall reagieren.

Wirklich sauber ist diese Lösung auch nicht, aber eine Lösung, die auf beide obere Varianten verzichtet und gleichzeitig den Verwaltungsoverhead, den jemand hat, der das Plugin schreibt, minimiert habe ich (noch) nicht.
 

moormaster

Top Contributor
Wie wäre es denn, wenn Plugins installiert werden müssen undzwar in der Form, dass der Quelltext eines Plugins zum Installieren des selbigen mit den gegenwärtigen Binaries der Interfaces compiliert wird?

Auf diese Weise würde man keine fremd-compilierten Binaries laden müssen und hätte somit nicht nur die richtige Version der Interfaces, sondern es sind sogar alle Plugins mit dem gleichen compiler compiliert worden :D
 

byte

Top Contributor
Lim_Dul hat gesagt.:
Gast hat gesagt.:
die richtige vorgehensweise wäre das neue interface von a abzuleiten sprich:

public interface Aneu extends A {
public void doSomeOtherThing();
}

dann weiß man auch zu jedem Zeitpunkt welches Interface gerade verwendet wird

Ideal wäre es, sowas überhaupt zu vermeiden ;)

Dieser Vorschlag hätte wieder den Nachteil, dass ich irgendwann eine riesige Kaskade von Interfaces habe A, A1, A2, ... An und das Testen, welche Version das zu ladende Plugin implementiert, in eine if instanceof Kaskade ausartet. Auch nicht schön :)


Naja, aber dafür gibts ja wiederum Muster, um sowas zu verhinern. Mir erscheint die oben angesprochene Lösung schon am sinnvollsten. Die Versionsbehandlung könnte man imo recht komfortabel mit ner Zuständigkeitskette realisieren. Die kannst Du nämlich Schritt für Schritt erweitern, ohne dabei die bereits implementierte Behandlung älterer Versionen verändern zu müssen. Anfragen werden dann automatisch vom richtigen Objekt behandelt, ohne dass Du unübersichtliche if instanceof Blöcke hast.
 

Lim_Dul

Top Contributor
Ich hol jetzt mal etwas weiter aus und erkläre, worum es geht.

Das Ziel ist es, Computergegner für ein von mir programmiertes Spiel zu implementieren.
Dabei soll es möglich sein, Computergegner extern zu programmieren und einfach als JAR Datei hinzuzufügen und im Programm zu nutzen.

Konkret geht es um das Brettspiel Carcassonne-

Nun hat das Spiel aber extrem viele Spieloptionen und damit auch sogenannte Spielmodi. Sei es Karte legen, Figur setzen, Drachen ziehen etc.

Idee, die mir momentan für die Bots im Kopf rumspukt ist die, dass es für jeden Modus eine Funktion im Interface gibt:

Code:
public ResultObject placeCard(GameInfoObjekt gameInfo);

Der Bot bekommt die Infos übergeben und liefert ein entsprechendes Ergebnis - wo er die Karten hinsetzen will - zurück.
Das ganze für jeden Modus. Vorteil der Sache ist, dass innerhalb des Bots keinerlei Verwaltungsoverhead der Form anfällt: "In welchem Modus bin ich, was soll ich tun".

Nachteil ist, dass es passieren kann, dass neue Spieloptionen und damit auch Spielmodi auftauchen, weil ich beispielsweise eine neue Erweiterung eingebaut habe. Das können dann die alten Bots nicht.

Aber jeder Bot muss zwingend eine Abfrage haben, wo man ihn Fragen kann, welche Optionen er überhaupt unterstützt. Das heißt in Spielen mit der neuen Option würde ein alter Bot nicht auswählbar sein und somit wäre garantiert, dass nur Methoden aufgerufen werden, die tatsächlich implementiert sind. (Was nicht heiß, das auf try/catch Abfragen verzichtet werden kann.)



Wie wäre es denn, wenn Plugins installiert werden müssen undzwar in der Form, dass der Quelltext eines Plugins zum Installieren des selbigen mit den gegenwärtigen Binaries der Interfaces compiliert wird?

Auf diese Weise würde man keine fremd-compilierten Binaries laden müssen und hätte somit nicht nur die richtige Version der Interfaces, sondern es sind sogar alle Plugins mit dem gleichen compiler compiliert worden
Alte Versionen liesen sich aber nur kompilieren, wenn zumindest leere Versionen der neuen Methoden implementiert würden.

Ich würde auch ungerne drauf verzichten alle alten Bots nutzlos zu machen, nur weil ich eine weitere Spieloption implementiere.

Ich könnte das natürlich auch so im Interface definieren:

Code:
public ResultObject doSomething(GameInfoObjekt gameInfo);

Und anhand von gameInfo.getModus() verzweigt der Bot dann in den jeweiligen Modus. Nachteil dieser Lösung wäre aber der Verwaltungsaufwan innerhalb der Bots, da jeder dann ein switch/case auf gameInfo.getModus() implementieren müsste.
Weiterhin würde ich damit die Fehlerbehandlung, wenn ein nicht implementierter Modus übergeben wird, in die Hände des jeweiligen Botprogrammieres legen. Das würde ich ebenfalls gerne vermeiden.


Von daher tendiere ich momentan noch zu der Variante, die NoSuchMethodExceptions werfen kann, auch wenn ich das Gefühl habe, dass dieses Design nicht ganz sauber ist.
 

moormaster

Top Contributor
Alte Versionen liesen sich aber nur kompilieren, wenn zumindest leere Versionen der neuen Methoden implementiert würden.

Ich würde auch ungerne drauf verzichten alle alten Bots nutzlos zu machen, nur weil ich eine weitere Spieloption implementiere.

Oder du nimmst statt eines Interfaces eine Klasse, von der alle Bots erben? Dann meckert der compiler nicht mehr über nicht implementierte Methoden und es sind auch alle Methoden erstmal existent (auch wenn die nicht überschrieben nix tun)

Nun könnte eine solche Methode in der Basisklasse immer null zurückliefern, wenn sie nicht überschrieben wurde, woran man erkennen kann, dass der bot das Feature nicht unterstützt.

Noch eine andere Variante wäre es, für jedes Feature ein neues Interface zu nehmen (bestehende Features dürfen sich dann natürlich nicht mehr ändern, aber da kann man vllt. zur Not auch noch Versionsnummern oder einfach schlüssige neue Bezeichnungen für ein weiteres Interface nehmen :D). Aber so könnte man jederzeit durch ein instanceof sehen, welcher Bot welches Feature implementiert.
 

Yzebär

Bekanntes Mitglied
Du solltest deine Bots versionieren. Du kannst dann auch zur Laufzeit die Bots fragen, welche Version sie haben und entsprechend nicht implementierte Spielmodi deaktivieren. Der Anwendung muß es egal sein, wie die Bots programmiert sind. Sie fragt nach der Version und weiß dann, welche Features der Bot unterstützt.

Ich würde für die Bots eine Hierachie aus abstrakten Klassen verwenden. Da kannst du die Schnittstellen festlegen und bestimmte Basisfuktionalität (auch Variablen, die Auskunft über die Version geben etc.) hinterlegen, die du für alle Bots verwenden kannst.
 

Lim_Dul

Top Contributor
Die Abfrage, was die Bots können ist obligatorisch. Daher kann ich auch garantieren, dass nur die Sachen aufgerufen werden, die tatsächlich unterstützt werden.

Ich hab auf jeden Fall jetzt erstmal ein paar weitere Möglichkeiten, über die ich nochmal in Ruhe nachdenken kann.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
C -Verschiedene Versionen eines Programms verwalten Allgemeine Java-Themen 7
C Verschiedene Versionen mit Datenbanken Allgemeine Java-Themen 3
J Verschiedene Runtime Versionen gleichzeitig? Allgemeine Java-Themen 12
H verschiedene Java Versionen Allgemeine Java-Themen 3
Thallius Verschiedene entities für gleichen Code…. Allgemeine Java-Themen 8
OnDemand Zentrale "Drehscheibe" für verschiedene APIs Allgemeine Java-Themen 14
M verschiedene Dokumente auslesen Allgemeine Java-Themen 1
MiMa Logging mit log4j2 in verschiedene Dateien? Allgemeine Java-Themen 22
H Klassen LibGDX - Verschiedene Klassen als Value in einer Map Allgemeine Java-Themen 8
P mehrer Verschiedene Objekte in einer Klasse erstellen. Allgemeine Java-Themen 4
K Verschiedene Sprachen Allgemeine Java-Themen 1
M Verschiedene Pilzartenerkennung Allgemeine Java-Themen 0
I Verschiedene Arrays auslesen Allgemeine Java-Themen 6
nrg Verschiedene JREs im Browser konfigurieren Allgemeine Java-Themen 6
S Best Practice verschiedene Exceptions fangen und neue Exception erzeugen Allgemeine Java-Themen 11
G DesignPattern Verschiedene Services Allgemeine Java-Themen 4
B Verschiedene Objekte in Abhängigkeit eines Typs instanziieren. Allgemeine Java-Themen 17
M massenhaft verschiedene Date-Pattern Allgemeine Java-Themen 3
R Eclipse Verschiedene Ergebnisse bei Berechnung eines double-Werts Allgemeine Java-Themen 5
R Implementierung eines Interface durch 2 verschiedene Klassen Allgemeine Java-Themen 6
faetzminator verschiedene Beans, verschiedene Felder "koppeln" Allgemeine Java-Themen 3
J Verschiedene Klassen als "Object" in ArrayList und dann in for-Schleife erzeugen!? Allgemeine Java-Themen 2
S Welche Datenstruktur für verschiedene Sprachen sinnvoll? Allgemeine Java-Themen 2
H Zwei verschiedene Dateien mittels einem Binärstream übertragen? Allgemeine Java-Themen 13
M verschiedene Methonden innerhalb des gleichen Threads Allgemeine Java-Themen 7
N verschiedene Klasse laden (Designfrage) Allgemeine Java-Themen 2
S Package in verschiedene Projekten einbinden? Allgemeine Java-Themen 3
D Verschiedene Datein aus einer Zip Datei ins Programm laden Allgemeine Java-Themen 4
D Verschiedene Persistenz Strategien Allgemeine Java-Themen 7
S Konstruktoren, verschiedene Klassen, Methoden. Allgemeine Java-Themen 3
M Verschiedene Modi bei AbstractTableModel Allgemeine Java-Themen 10
J Verschiedene Klassen, verschiedene Ströme? Allgemeine Java-Themen 6
V 1 Methode für viele verschiedene Klassen? Allgemeine Java-Themen 9
J Verschiedene Starteinstellungen Allgemeine Java-Themen 7
J Programm für verschiedene Betriebssystem vertreiben? Allgemeine Java-Themen 10
M 2 verschiedene LookAndFeels in einem Fenster möglich? Allgemeine Java-Themen 6
D Gehts praktischer? Thema:Verschiedene Instanzen einer Klasse Allgemeine Java-Themen 3
C Verschiedene JDKs Allgemeine Java-Themen 6
M Regular Expression - verschiedene Ausdrücke testen (grep | ) Allgemeine Java-Themen 5
C verschiedene Klassenarten Allgemeine Java-Themen 3
G Verschiedene Auflösungen Allgemeine Java-Themen 6
A Textfeld soll verschiedene Datumseingaben akzeptieren Allgemeine Java-Themen 5
T ändern neue Java Versionen was an der Programmiersprache? Allgemeine Java-Themen 15
S Probleme mit unterschiedlichen Java-Versionen (Mac OS X 10.11) Allgemeine Java-Themen 0
P Mehrere Java Versionen auf dem Rechner Allgemeine Java-Themen 3
F Webstart zwei Java Versionen / aktivieren bzw deaktivieren Allgemeine Java-Themen 2
J Jars in unterschiedlichen Versionen Allgemeine Java-Themen 14
Shoox Java-Versionen Allgemeine Java-Themen 5
M Unterschiedliche Java-Versionen Allgemeine Java-Themen 5
R Testen von Applets - versch. Browser und Java Versionen? Allgemeine Java-Themen 4
G jar und Java-Versionen Allgemeine Java-Themen 4
G JDBC Programm und niedrige Java-Versionen Allgemeine Java-Themen 14
M Java Versionen über Skript aktivieren/deaktivieren? Allgemeine Java-Themen 2
ARadauer Java Versionen Übersicht Allgemeine Java-Themen 2
T JDBC: Unterschiede in Interfaces zwischen 2 Java-Versionen. Allgemeine Java-Themen 6
C Auswahl einer Version, bei mehreren installierten Versionen Allgemeine Java-Themen 3
T Installierte JRE Versionen Allgemeine Java-Themen 4
B Mehrere Versionen auf einem Rechner Allgemeine Java-Themen 2
M Erweiterungen in späteren Java-Versionen Allgemeine Java-Themen 26
S Probleme mit Java Versionen und Commapi Allgemeine Java-Themen 2
F Mehrere Versionen von Java auf einem W2K Desktop Allgemeine Java-Themen 3
U Transparent Buttons - unterschiedliche Java-Versionen Allgemeine Java-Themen 8
D Die Versionen Standard, Enterprise und Micro Allgemeine Java-Themen 3
D Windows-Versionen und Befehlsinterpreter Allgemeine Java-Themen 5
O regulärer Ausdruck zum durchsuchen eines Strings verwenden Allgemeine Java-Themen 2
T Rotationswinkel eines Bildes bestimmen Allgemeine Java-Themen 4
C Probleme beim Erstellen eines runnable-jar files Allgemeine Java-Themen 1
J JavaScript innerhalb eines Java Projekts ausführen Allgemeine Java-Themen 2
Encera Größe eines Objektes in Byte berechnen Allgemeine Java-Themen 2
8u3631984 Prüfen ob min. ein Element eines Sets in einem anderen Set enh Allgemeine Java-Themen 4
M Array Rang eines Elements Allgemeine Java-Themen 4
OnDemand Teile eines Links entfernen Allgemeine Java-Themen 6
H Auslesen eines (LDAP-)Attributs in Active Directory Allgemeine Java-Themen 2
W JSON parsen eines ,mit JS.stringify erstellten Strings Allgemeine Java-Themen 27
H Textposition eines gedrehten Textes verschieben Allgemeine Java-Themen 8
berserkerdq2 run-methode eines Threads so programmieren, dass 30x die Sekunde etwas ausgeführt wird. Allgemeine Java-Themen 44
E Ersetzen eines Bildes in der Kopfzeile eines Word-Docx-Dokuments mit Apache POI XWPF Allgemeine Java-Themen 0
N Fahrtrichtung eines selbstfahrenden Auto ändern Allgemeine Java-Themen 3
T Letztes Zeichen eines Strings enfernen Allgemeine Java-Themen 14
S Übergabe eines Sortierkriteriums für ein Artikel Array mittels BiPredicate<Artikel, Artikel> Allgemeine Java-Themen 13
gotzi242 Schatzsuche mithilfe eines O(log n) Algorithmus Allgemeine Java-Themen 2
C Koordinaten LONG/LAT eines neuen Punktes in bestimmter Entfernen und Winkel berechnen Allgemeine Java-Themen 3
Tobero Meine Funktion für das beinhalten eines Punktes in einem Kreis funktioniert nicht Allgemeine Java-Themen 5
LimDul Direktes return eines Array geht nicht Allgemeine Java-Themen 20
S Mittelwert anhand eines Stream berechnen Allgemeine Java-Themen 5
kodela Breite eines erweiterten Monitors feststellen Allgemeine Java-Themen 5
R Zeilen eines 2d Arrays abwechselnd links und rechts mit Nullen auffüllen Allgemeine Java-Themen 14
Zrebna Alternative Darstellung eines Codesnippets Allgemeine Java-Themen 33
kodela Inhalt eines Arrays ändert sich mysteriös Allgemeine Java-Themen 2
bueseb84 Wget mit Wildcards - oder wie lädt man bei JFrog die letzte Version eines Artifacts herunter Allgemeine Java-Themen 3
N Erkennen eines Programs Allgemeine Java-Themen 2
N Pausieren eines Programmes Allgemeine Java-Themen 4
D Input/Output Implementierung eines CommandHandlers/Parsers für viele Eingaben Allgemeine Java-Themen 26
M Gibt es eine API die den aktuellen Wert eines Indikators beim Trading zurückgibt? Allgemeine Java-Themen 7
F Wie bekommt man alle Filenamen eines Webserver Verzeichnisses Allgemeine Java-Themen 6
A Fehler beim Öffnen eines Projekts Allgemeine Java-Themen 6
N Eigenschaften eines Buttons per Setter verändern Allgemeine Java-Themen 5
S Ausfuehrung eines Programms aufzeichnen..? Allgemeine Java-Themen 4
X Ermittlung eines doppelte Paars mit Streams Allgemeine Java-Themen 50
Stonie Prüfen von direkter Implementierung eines Interfaces Allgemeine Java-Themen 7

Ähnliche Java Themen

Neue Themen


Oben