Frage von Alinchen24, 91

Was bedeuten diese Begriffe in Java?

Überladen, überschreiben, statisches und dynamisches Binden. Irgendwie verstehe ich nämlich nix, wenn ich google.

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von triopasi, 33

1. Benutze doch die englischen Begriffe, die sind viel besser und die versteht jeder. Was du zB mit "bindung" meinst, kA.

2. Überladen: "In some programming languages, function overloading or method overloading is the ability to create multiple methods of the same name with different implementations."

3. Überschreiben: "Method overriding, in object oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes."

Siehe auch hier: http://stackoverflow.com/questions/837864/java-overloading-vs-overwriting

Kommentar von regex9 ,

Ob er nun dynamic / static binding schreibt, oder die Worte in Deutsch übersetzt, macht hier keinen Unterschied.

Antwort
von regex9, 41

Überladen:

Wenn eine Elementfunktion eine andere Signatur besitzt. Die Signatur besteht aus ihrem Namen und der Parameterliste, wobei auch die Reihenfolge und der Typ der Parameter entscheidend ist. Ein Beispiel:

void rechne(){}
void rechne(int a){}

Die Elementfunktion rechne wird von der zweiten Elementfunktion rechne überladen, da sich die Signatur unterscheidet.

Überschreiben:

Wenn eine Elementfunktion in einer Klasse die gleiche Signatur besitzt, wie die geerbte einer Basisklasse / eines Interfaces. In der Praxis definiert man bspw. in der Basisklasse ein abstraktes Verhalten, bspw. wie ein Tier (abstrakte Basisklasse) läuft. Die konkretere Klasse Jaguar dagegen kann das Verhalten explizit überschreiben, weil der Jaguar vielleicht nicht läuft wie andere Tiere, sondern große Sprünge macht. o.ä.. Ein Beispiel:

class Tier {
void laufen() {}
}

class Jaguar extends Tier {
@Overide
void laufen() {}
}

Die Annotation @Override sagt dem Compiler hierbei explizit, dass die Methode laufen überschrieben werden soll.

Hätte laufen (vom Jaguar) dagegen einen zusätzlichen Parameter, wäre es wiederum eine Überladung.

Statische und dynamische Bindung:

Später, bei der Kompilierung, muss aufgelöst werden, welche Methode der Compiler nun nutzen soll. Nimm an, es wurde ein Objekt Jaguar erzeugt und die Methode laufen aufgerufen. Dann muss der Compiler schauen, wo sich die Methode befindet bzw. welche er nutzen soll. In diesem Fall ist es ganz simpel:

Jaguar jaguar = new Jaguar();
jaguar.laufen();

Der Compiler schaut in die Klasse des Objekts, und ruft die gefundene Methode auf. Es ist eine statische Bindung, denn es ist von Beginn an klar, welche Methode aufgerufen wird.

Tier tier = new Jaguar();
tier.laufen();

Hier ist es etwas anders. Es wurde ein Objekt der Klasse Jaguar kreiert, dieses aber via Polymorphie als Tier gewrappt. Nun muss zur Laufzeit entschieden werden, welche Methode er nun aufrufen soll, denn der Typ ist dynamisch. Der tatsächliche Typ von tier ist nicht Tier, sondern Jaguar. Also löst er das Objekt auf, schaut in dessen Klasse und wandert den Vererbungsbaum immer weiter nach oben, auf der Suche nach dem ersten Fund angegebener Methode. Diese wird genutzt. Man spricht dabei von später Bindung.

Kommentar von Berny96 ,

Mich fasziniert gerade die Ähnlichkeit unserer Antworten ^^

Antwort
von Berny96, 29

Überladen

Wenn eine Klasse mehr als nur einen Konstruktor besitzt. Konstruktor werden immer aufgerufen wenn eine Instanz der Klasse erstellt wird. Je nach dem wie der Konstruktor geschrieben wurde muss man dann auch Argumente mitgeben. z.B. wenn ich eine Instanz der Klasse "Ball" erstelle müsste ich vielleicht eine größe mitgeben. Das sähe dann so aus:

Ball meinBall = new Ball(10);

Die Klasse Ball hat in dem Moment einen Konstruktor der die Größe des Balls annimmt damit er die Instanz entsprechend vorbereiten und die Größe auf 10 setzen kann. Sollte aber die Klasse Ball eine weiter Möglichkeit bieten sie zu instanzieren wie z.B. dass man zusätzlich noch eine Farbe angibt

Ball meinBall = new Ball(10, "Grün");

dann ist die Klasse "Überladen". Dies gilt auch für Methoden die unterschiedliche Parameter annehmen.

Überschreiben


Eigentlich ganz selbstverständlich. Hier handelt es ich um Vererbung. Wenn man eine Basisklasse "Person" hat mit einer Methode "Laufen" und eine weitere Klasse "Kind" welche von Person erbt dann kann man die Laufen Methode überschreiben damit Instanzen von Kind anders laufen als Instanzen von Person. So könnte man zum Beispiel in einem Spiel die Geschwindigkeit der beiden Fälle anpassen. 



Statisches und Dynamisches Binden

Hier muss man ein paar grundlegende Sachen der Programmierung verstanden haben und zwar Referenzierungen und Instanzen. Statisches binden ist das was wir bisher getan haben. Wir erstellen eine Instanz der Klasse Person und rufen die Laufen Methode auf. Der Compiler weiß genau welche Laufen Methode gemeint ist da Person die Basisklasse ist und das erste Erscheinen der Laufenmethode ist. Da man aber Referenzierungen erstellen kann die eigentlich auf Unterklassen verweisen kann es mal passieren dass z.B. beim Überschreiben von Methoden man die Laufen Methode aufruft und aber zwei mögliche Methoden vorhanden sind. Einmal die von Person und die von Kind.

Person einKind = new Kind();
einKind.Laufen();

Die Referenztyp ist in dem Fall vom Typen Person. Das eigentliche Objekt was dahinter steckt ist aber vom Typ Kind. Der Compiler findet also erst beim Compilieren heraus welche Laufen Methode er aufrufen soll. Das nennt man Dynamisches Binden. Im Vergleich nochmal kurz das statische Binden:

Kind einKind = new Kind();
einKind.Laufen();

Hier ist ganz klar: Rufe die Methode Laufen der Klasse Kind auf.

Kommentar von regex9 ,

Die dynamische Bindung wird erst zur Laufzeit aufgelöst, nicht bei der Kompilierung.

Antwort
von Schachpapa, 27

überschreiben bedeutet, dass eine Methode in einer erbenden Klasse mit gleicher Signatur neu geschrieben wird und damit die gleichnamige aus der Oberklasse ersetzt.

überladen bedeutet, dass eine Methode mit gleichem Namen aber anderer Parameterliste (andere Typen oder andere Parameterzahl) in der Klasse oder einer Unterklasse geschrieben wird und damit neben der anderen exisitiert.

statisches vs. dynamisches Binden macht sich bemerkbar, wenn man ein Objekt einer Unterklasse wie eine Oberklasse referenziert.

Vgl: http://www2.math.uni-wuppertal.de/~schaefer/jv/haupt/node41.html

@myself: wieder was dazugelernt: getter machen auch bei public Variablen Sinn


Kommentar von regex9 ,

Und wieso machen Getter auch bei sichtbaren Feldern Sinn?

Kommentar von Schachpapa ,

Ich fand das Ergebnis dieses Tests etwas überraschend

public class Ober {
public String inhalt = "Ober-Inhalt";

public String getInhalt() {
return inhalt;
}
}

public class Unter extends Ober {
public String inhalt = "Unter-Inhalt";

public String getInhalt() {
return inhalt;
}
}

public class BinderTest {
public static void main(String[] args) {
Ober o = new Ober();
Unter u = new Unter();
Ober o2 = u;

System.out.println("o.inhalt : "+o.inhalt);
System.out.println("u.inhalt : "+u.inhalt);
System.out.println("o2.inhalt : "+o2.inhalt);
System.out.println("o.getInhalt : "+o.getInhalt());
System.out.println("u.getInhalt : "+u.getInhalt());
System.out.println("o2.getInhalt : "+o2.getInhalt());
}
}
Dass Variablen und Methoden verschieden behandelt werden, war mir bis dato nicht klar. Allerdings bin ich bisher auch nie auf die Idee gekommen Instanzvariablen zu überschreiben.

Interessant auch, wenn man den getter in Unter weglässt ...

Kommentar von regex9 ,

Man redet in diesem Fall auch nicht von Überschreiben, sondern von Überdecken (so wie eine lokale Variable ein Instanzfeld überdecken kann). Hierbei entscheidet der Kontext. Der abstrakte Typ weiß nicht, dass er konkret das vererbte Feld überdeckt, nutzt also den ihm bekannten Zustand. Zumal dieses Feld einen komplett anderen Datentyp aufweisen kann:

class Basis {
   public int feld;
}

class Kind extends Basis { public String feld;
}
class Test { public static void main(String[] args){ Basis basis = new Kind(); basis.feld = 2; Kind kind = new Kind(); kind.feld = "Kind"; } }

Keine passende Antwort gefunden?

Fragen Sie die Community