Technische Realisierung eines Interface

kossy

Bekanntes Mitglied
Hallo !

Ich habe eine Frage an euch (auch wenn diese rein theoretisch ist und eigentlich keinen konkreten Praxisnutzen hat). Wenn ich ein Interface in einer beliebigen OOP Sprache nutze (in unserem Fall Java) und dieses Interface von z.B. drei verschiedenen Klassen auf unterschiedlichste Weise implementiert wird (also die Methoden, die dort in dem Interface stehen), dann habe ich ja die Möglichkeit, einer Referenzvariable vom Typ des implementierten Interface die Objekte zuzuweisen, welche dieses Interface implementieren und dann die Methoden über die Referenzvariable aufzurufen.

Damit soll ja die Wartbarkeit, Flexibilität und ein dynamisches Austauschen der Objekte an der Referenzvariable vom Typ des Interface zur Laufzeit ermöglicht werden.

Was mich jetzt interessiert. Wie genau wird den technisch erkannt, dass ein Objekt tatsächlich dieses eine Interface implementiert hat, welches der Referenzvariable entspricht.

Wie genau wird das technisch ermöglicht? Geht das evtl. computerintern über eine zentrale Speicheradresse, die abgeglichen wird (also stimmt die Speicheradresse des Interface bzw. der Referenzvariable mit dem Interface überein, welches das beliebige Objekt implementiert hat und wenn ja, dann läuft der Code durch, ansonsten gibt es einen Compilerfehler)?

Analog gilt die Frage eben auch zu einer Referenzvariable vom Typ einer abstrakten Klasse, welcher ein Objekt zugewiesen wird, die die abstrakte Klasse erweitert.

Gruß
Kossy
 
Jede Class-Datei in Java zeigt an, welche Interfaces eine Klasse implementiert und welche die Superklasse ist (bis auf [c]Object[/c]). Darauf greifen sowohl der Compiler als auch die Laufzeit zu. Die Zuordnung geschieht rein über Strings. Wenn eine Klasse [c]pkg.Foo[/c] das Interface [c]pkg.IFoo[/c] implementiert, steht in der Klassendefinition von [c]Foo[/c] als Superklasse [c]java/lang/Object[/c] und als Interface [c]pkg/IFoo[/c] (intern sind es Schrägstrichte statt Punkte). Diese werden dann dynamisch aufgelöst; zur Laufzeit kommt da die komplette Classloader-Schiene zum Einsatz, was das Ganze unter Umständen recht komplex werden lässt, der Compiler sucht afaik einfach nur linear im Classpath.
 
Ich weiss jetzt nicht genau wie das bei OOP z.B. in C++ oder D funktioniert, aber ich hab mir die Frage auch gestellt und bin zu em Schluss gekommen:
Du deklarierst ein Interface und eine Klasse die das implementiert
Code:
interface Bla {
    void methode1();
    void methode2();
}
class Foo implements Bla {
    void methode1() {
        // Code!
    }
    void methode2() {
        // Code!
    }
}
und eirgendein code verwendet das
Code:
Bla object=new Foo();
Dann weiss der Compiler, dass er in den bytes die von [c]object[/c] referenziert werden in den Bytes x-y findet, wo der Code für die implementierungen von [c]methode1()[/c] bzw. [c]methode2()[/c] stehen. Bei runtime wird dann die CPU angewiesen genau dort hin zu springen. Somit kann der code sein, wie und so lang er will.
 
Zuletzt bearbeitet:
In Java ist gibt es 2 Möglichkeiten. Entweder es gibt einen Compile-Fehler oder einen Runtime-Fehler. Im Prinzip läuft es immer auf try and error raus.

Bei:

Java:
MyInterface my = (MyInterface)"String";

Weiß der Compiler schon das ein String nicht MyInterface implementiert, denn zum kompilieren hat der Compiler schon alle Informationen über Typ-Hierarchien zur Verfügung.

Bei:

Java:
public void foo(Object bar){
     MyInterface my = (MyInterface)bar;
}

Kann es in die Hose gehen oder auch nicht. Kommt drauf an ob bar MyInterface implementiert oder auch nicht. m Bytecode wird erst einmal geschaut ob der Cast passt, falls nicht wird eine ClassCastException geworfen. Spezifiziert ist das hier Checkcast.
 

Zurück
Oben