OOP Definition / Abgrenzung dynamische Bindung

Hey ho,

ich denke mir ist das Prinzip der dynamischen Bindung recht klar zumindest verhält sich Java exakt so wie ich es erwarte und ich kann damit arbeiten. Aber demnächst steht bei mir eine Klausur an und da geht es dann leider mehr um die Theorie und da fehlt mir so ein bisschen die "klare Abgrenzung" wann man noch von dynamisch spricht und wann von statisch. Und leider ist das eine gern gesehene Aufgabe da man das schön auf dem Papier lösen kann. Der Code ist gegeben und beurteilt muss werden ob dynamisch oder statische Bindung vorliegt.

Um das ganze weniger abstrakt zu machen vielleicht an Hand eines einfachen Beispiels:
Java:
class A {

    protected String s = "A:s";
    protected String t = "A:t";
    public String s() {
        return s;
    }
    public String t() {
        return t;
    }

}

class B extends A {

    protected String s = "B:s";
    protected String t = "B:t";

    public String s() {
        return s;
    }
}

public class PolyTest {

    public static void main(String[] args) {

        B b = new  B();
        A a = b;
        System.out.println( b.s() ); // statisch?
        System.out.println( a.s() ); // dynamisch?
        System.out.println( b.t() ); // statisch?
        System.out.println( a.t() ); // statisch?
   
    }
}

Was wieso ausgegeben wird ist mir absolut klar. Aber wo ich mir nicht ganz sicher bin ist bei folgenden Fällen die formelle Definition:

Bei
Java:
A a = new B();
println(a.s);
würde ich klar sagen es ist eine dynamische Bindung.

Aber bei
Java:
B b = new B();
println(b.s);
ist ja im Grunde schon durch die Deklaration die Methode klar da schon beim kompilieren zur gleichen Methode aufgelöst werden müsste wie zur Laufzeit. Dennoch bestimmt ja am Ende schon "new B();" über den VMT welche Methode aufgerufen wird (auch wenn es dann schon auf die richtige zeigt) und "new B();" ist ja vom dynamischen Typ. Ich würde jetzt ansich sagen es ist eine statische Bindung aber da new B() ja immer dynamisch ist weiss ich nicht wie man das formell benennt. Also spricht man allgemein immer von einer dynamischen Bindung bei Objektmethoden oder nur wenn tatsächlich eine Methode überschrieben wurde + die Variable den Typ des Vorfahrens der Klasse hat? Also tatsächlich dynamisch die Methode zur Laufzeit gegenüber der vom Compiler geändert wurde?

Also wären
Java:
A a = new A();
B b = new B();
println(a.s);
println(b.s);
println(t.s);
println(t.s);
alle statisch gebunden?

Und nur
Java:
A a = new B();
println(a.s);
dynamisch?

Vielleicht kann mir ja jemand helfen wie man das so definiert. Unser Script sagt leider nur:
"Bei Variablen statische Bindung, bei Methoden dynamisch! Zur Compilezeit nur der Statische Typ sicher, daher auch die entsprechende Variablen benutzt. Auch die Signatur einer Methode steht dann fest"
..wenig hilfreich.. es sei denn es ist wirklich allgemein so, dass man bei Methoden dann immer von einer dynamischen Bindung ausgeht was ich mir so aber nicht vorstellen kann?!
 
Vielleicht kann mir ja jemand helfen wie man das so definiert. Unser Script sagt leider nur:
"Bei Variablen statische Bindung, bei Methoden dynamisch! Zur Compilezeit nur der Statische Typ sicher, daher auch die entsprechende Variablen benutzt. Auch die Signatur einer Methode steht dann fest"
..wenig hilfreich.. es sei denn es ist wirklich allgemein so, dass man bei Methoden dann immer von einer dynamischen Bindung ausgeht was ich mir so aber nicht vorstellen kann?!
Ich würde an der Stelle auf das Skript hören 😉

Die Methoden oben sind alle dynamisch gebunden
 
Also Java kennt keine statische Bindung von Methoden, außer sie sind statisch oder final (bei diesem bin ich mir nicht sicher).

Somit sind aus deinem Beispiel alle Methodenaufrufe dynamisch. Bei den letzten beiden Aufrufen hast du das Problem von Shadowing du überschreibst die Objektvariable t. Richtig wäre:
Java:
class B extends A {
 
  protected String s = "B:s";
 
  public B() {
    t = "B:t";
  }
 
  public String s() {
    return s;
  }
}

EDIT: Gerade verifiziert. final Methoden werden auch mit invokevirtual aufgerufen.
 
Zuletzt bearbeitet:
Also Java kennt keine statische Bindung von Methoden, außer sie sind statisch oder final (bei diesem bin ich mir nicht sicher).
private Methoden und Konstruktoren noch 😉

EDIT: Gerade verifiziert. final Methoden werden auch mit invokevirtual aufgerufen.
Ja, die gehen nicht, weil man das final wegnehmen kann, und die Klasse trotzdem noch kompatibel ist.


Wobei das natürlich wieder anders aussieht, wenn man den Hotspot-Compiler statt javac betrachtet...
 
private Methoden und Konstruktoren noch 😉
Konstruktoren & private Methoden werden mit #invokespecial betrieben und auf private Methoden hat man von außerhalb so und so keinen Zugriff.
Ja, die gehen nicht, weil man das final wegnehmen kann, und die Klasse trotzdem noch kompatibel ist.
final funktioniert nicht, weil schon die finale Methode schon überschrieben sein kann und von daher braucht man das dynamisch.
 
Zuletzt bearbeitet:
Danke für die zahlreichen Antworten. Den Insel Artikel kenne ich und wie gesagt der Mechanismus als solches ist mir relativ klar. Es ist ja ansich auch deutlich einfacher wenn man einfach von dynamischer Bindung ausgeht ausser bei privaten/statischen/finalen Methoden. Aber das Problem ist irgendwie wird diese Unterscheidung nicht so wirklich konsequent so gemacht.

Z.b schreibst du Flown im Polymorphie Post von Kiimarii
Auweia das ist ein wenig ein komplexeres Thema, aber hier tritt kein einziges mal dynamic dispatching (dynamische Bindung) auf.

Aber eurer Aussage nach müssten die Methoden (wie "x.m(most);" usw ja dann auch alle dynamisch gebunden sein?!

Und in dem genannten Insel Artikel steht z.B
Das liegt daran, dass nur überschriebene Methoden an dynamischer Bindung teilnehmen, und wenn es kein Überschreiben gibt, dann gibt es auch keine dynamische Bindung.

Würde ja in meinem Beispiel eigentlich bedeuten, dass die Methode t da sie nicht überschrieben wurde nicht an dynamischer Bindung teilnimmt. Also mir ist schon klar dass die t() immer noch einer virtuelle Methode ist etc und die Auswahl der tatsächlich auszuführenden Methode zur Laufzeit anhand des zugewiesenen Objektes erfolgt was eigentlich definitionsgemäß eine dynamsiche Bindung darstellt. Aber sei es in der Literatur oder auch so von Leuten wird oft nur dann von dynamischer Bindung gesprochen, wenn auch überschrieben wurde etc.

Mit der Überschattung ist ein guter Hinweis.. da sieht man mal wie schnell sich sowas "einschleicht" 😉
 
Konstruktoren & private Methoden werden mit #invokespecial betrieben und auf private Methoden hat man von außerhalb so und so keinen Zugriff.
Was doch durchaus ein Äquivalent zum statischen Binding ist - die Methode steht schon zur Kompilezeit fest und hängt nur vom statisch Typ ab.

final funktioniert nicht, weil schon die finale Methode schon überschrieben sein kann und von daher braucht man das dynamisch.
Warum sind denn die weiter oben in der Hierarchie liegenden Methoden relevant?
Wenn sie für den statischen Typ als final deklariert ist, sollten die dabei doch die Supertypen egal sein

Oder meinen wir beide das gleiche - das ein zur Kompilezeit finaler und statisch feststehender Methodenauftuf zur Laufzeit nicht mehr final und damit ein anderer sein kann?
 
Oder meinen wir beide das gleiche - das ein zur Kompilezeit finaler und statisch feststehender Methodenauftuf zur Laufzeit nicht mehr final und damit ein anderer sein kann?
Im Grunde ja.
Aber das Problem ist irgendwie wird diese Unterscheidung nicht so wirklich konsequent so gemacht.
Klar wird alles durchgezogen ist auch in der JLS so spezifiziert.
Aber eurer Aussage nach müssten die Methoden (wie "x.m(most);" usw ja dann auch alle dynamisch gebunden sein?!
Die Methoden sind dynamisch gebunden, aber da der outcome nicht so wie erwartet ist, hat nichts mit dynamic dispatching zu tun. Sondern mit der Sichtbarkeit von Methoden des statischen Typs, also eine komplett andere Baustelle. Hab auch ein Beispiel dazugeschrieben, wie es dann dynamic dispatched wird.
Würde ja in meinem Beispiel eigentlich bedeuten, dass die Methode t da sie nicht überschrieben wurde nicht an dynamischer Bindung teilnimmt.
Grob gesagt, jede öffentliche Methode wird mit invokedynamic aufgerufen. Wenn jetzt keine Methode überschrieben wird, dann gibt es sozusagen keine "Auswahl" oder "Konkretisierungen" und ist im engeren Sinne keine dynamische Bindung, weil was soll ohne Auswahl denn dynamisch sein?!
 
Die Methoden sind dynamisch gebunden, aber da der outcome nicht so wie erwartet ist, hat nichts mit dynamic dispatching zu tun. Sondern mit der Sichtbarkeit von Methoden des statischen Typs, also eine komplett andere Baustelle. Hab auch ein Beispiel dazugeschrieben, wie es dann dynamic dispatched wird.
In dem anderem Beispiel werden allerdings auch Methoden überschrieben, das ist schon dynamic dispatch 😉
 

Neue Themen


Zurück
Oben