Hallo alle zusammen,
ich komme eigentlich von C, daher vermute ich mal, dass mein Thema eher in die Kategorie Anfänger gehört.
Ich schreibe ein Plugin für ein Tool und binde dafür die API von dem Tool ein. Die Methoden geben mir ein Interface auf Elemente des Tools zurück. Jetzt würde ich gerne einige der Methoden der Elemente erweitern und wollte dazu von der Interface-Klasse ableiten - da wusste ich aber noch nicht, dass es nur ein Interface ist. Die Klasse, die das Interface implementiert, ist nicht dokumentiert. Kann ich trotzdem irgendwie die Klasse erweitern?
Meine Alternative wäre, meine Methoden prozedural in meine eigene Klasse zu schreiben. Aber ich will ja objektorientiert.
Gruß,
Heimchen
PS: Das Original-Interface kann ich nicht bearbeiten.
Natürlich kannst du auch Klassen ableiten (auch wenn du den Source-Code nicht besitzt), wenn sie die richtige Sichtbarkeit aufweisen und nicht final sind.
Der Name der Klasse ist mir leider nicht bekannt. Das Problem ist, dass mein erweitertes Interface ja auch gleich die Implementierung meiner Erweiterung enthalten müsste, weil es ja nach wie vor von der Klasse der API implementiert wird.
Vielleicht macht es das etwas deutlicher. IApi ist das Interface, was ich über die Api abfragen kann, um Elemente meines Tools zu bearbeiten:
Java:
IApi e =getElement();
e.apiMethod();
Ich möchte jetzt quasi sowas haben:
Java:
publicinterfaceIMyApiextendsIApi{voidmyMethod(){return;}}IMyApi e =(IMyApi)getElement();
e.apiMethod();
e.myMethod();
Ist das jetzt ein XY Problem? Kannst du genau sagen was du machen willst? Denn so funktioniert das nicht.
Wenn getElement() eine IApi zurückgibt kannst du da nicht casten oder implementierst du getElement()?
Nein, ich implementiere nicht getElement(). Es sieht auch in echt so aus:
Java:
import externalToolApi;// implements method "static IApi getElement();"importIApi;publicclass myClass {staticvoidmain(String[] args){IApi e = externalToolApi.getElement();
myClass.myMethod(e);}staticvoidmyMethod(IApi e){// Tu irgendwas mit e}}
Statt myMethod prozedural aufzurufen, würde ich gerne objektorientiert arbeiten. Probiert hab ich das:
Java:
import externalToolApi;// implements method "static IApi getElement();"importIApi;publicinterface myApi extendsIApi{voidmyMethod(){// Tu irgendwas mit this}}publicclass myClass {staticvoidmain(String[] args){IMyApi e = externalToolApi.getElement();
e.myMethod(e);}}
Wenn mich nicht alles täuscht, ist das in C recht einfach wie beschrieben möglich, weil es keine expliziten Interfaces gibt. Da kann ein Interface auch eine Implementierung enthalten.
Wie schon @stg erwähnt hat würde ich Kompositionen nutzen. Das heißt das von getElement() zurück gegebene Objekt einfach in einem eigenen Klasse Wappen und die Klasse implementiert dein MyAPI Interface. Wobei der Name hier des Interfaces nix sagend ist...
Damit kannst du dann die Methode die du von der externen API nutzt weiter delegieren und deine eigenen Methode hinzufügen.
Ich glaube diese Idee wird auch im Buch Working with Legacy Code erwähnt. Damit bekommst du ein schönes Design da du die unterliegende Bibliothek komplett von deinem Code Abstract machst und so es ermöglichst einfach die Bibliothek aus zu tauschen.
Was du hier nachzubauen versuchst sind Extension-Methods und werden in Java in dieser Form nicht unterstützt. Also ich würde wie @stg schon gesagt hat einen Wrapper um dieses Objekt bauen.
PS: Wo ist jetzt der Unterschied von den einem Codesnippet zu den anderen?
Die Frage ist brauchst du alle 50 Methode ? Oder reichen dir 3 für den Anfang und die anderen kommen dann im Laufe des Projektes.
Kannst ja auch zwei Interface machen, einmal das Wrapper Interface und dein Interface mit eigenen Methode, das vom Wrapper Interface erbt. Damit kannst du zwei Implementierungsklassen machen und hast den Code einwenig separiert.
Da waren ein paar kleine Verschreiber, z.B. IMyApi vs. myApi, etc.
Das mit dem Wrapper scheint zu gehen. Das mit dem Delegieren in Eclipse kannte ich noch nicht.
Bekomme ich das denn auch so hin, dass sich das Handling mit meinem Wrapper-Interface nicht von dem der ursprünglichen API-Interfaces unterscheidet? In etwa so:
Java:
IApi1 eins = externalToolApi.getElement1();
eins.foo();IApi2 zwei = externalToolApi.getElement2();
zwei.baa();IMyApi drei = externalToolApi.getElement3();
drei.myFooBaa();
publicinterfaceAPIWrapper{// Methoden die du von IApi wrappen willstvoidmethodeA();// ....}publicinterfaceMyAPIextendsAPIWrapper{// Deine Methoden die du selbst implementierstvoidmyMethodeA();//...}