JavaRush /Java-Blog /Random-DE /Polymorphismus und seine Freunde
Viacheslav
Level 3

Polymorphismus und seine Freunde

Veröffentlicht in der Gruppe Random-DE
Polymorphismus ist eines der Grundprinzipien der objektorientierten Programmierung. Es ermöglicht Ihnen, die Leistungsfähigkeit der starken Java-Typisierung zu nutzen und verwendbaren und wartbaren Code zu schreiben. Es wurde schon viel über ihn gesagt, aber ich hoffe, dass jeder aus dieser Rezension etwas Neues mitnehmen kann.
Polymorphismus und seine Freunde - 1

Einführung

Ich denke, wir alle wissen, dass die Programmiersprache Java zu Oracle gehört. Daher beginnt unser Weg mit der Website: www.oracle.com . Auf der Hauptseite gibt es ein „Menü“. Darin gibt es im Abschnitt „Dokumentation“ einen Unterabschnitt „Java“. Alles, was sich auf die Grundfunktionen der Sprache bezieht, gehört zur „Java SE-Dokumentation“, daher wählen wir diesen Abschnitt aus. Der Dokumentationsbereich wird für die neueste Version geöffnet, aber vorerst wird die Meldung „Suchen Sie nach einer anderen Version?“ angezeigt. Wählen wir die Option: JDK8. Auf der Seite sehen wir viele verschiedene Optionen. Aber wir sind daran interessiert, die Sprache zu lernen: „ Java Tutorials Learning Paths “. Auf dieser Seite finden wir einen weiteren Abschnitt: „ Erlernen der Java-Sprache “. Dies ist das Allerheiligste, ein Tutorial zu Java-Grundlagen von Oracle. Java ist eine objektorientierte Programmiersprache (OOP), daher beginnt das Erlernen der Sprache auch auf der Oracle-Website mit einer Diskussion der Grundkonzepte der „Konzepte der objektorientierten Programmierung “. Aus dem Namen selbst geht hervor, dass Java auf die Arbeit mit Objekten ausgerichtet ist. Aus dem Unterabschnitt „ Was ist ein Objekt? “ geht klar hervor, dass Objekte in Java aus Zustand und Verhalten bestehen. Stellen Sie sich vor, wir hätten ein Bankkonto. Der Geldbetrag auf dem Konto ist ein Zustand, und die Methoden, mit diesem Zustand zu arbeiten, sind Verhalten. Objekte müssen irgendwie beschrieben werden (geben Sie an, welchen Zustand und welches Verhalten sie haben können), und diese Beschreibung ist die Klasse . Wenn wir ein Objekt einer Klasse erstellen, geben wir diese Klasse an und dies wird als „ Objekttyp “ bezeichnet. Daher wird gesagt, dass Java eine stark typisierte Sprache ist, wie in der Java-Sprachspezifikation im Abschnitt „ Kapitel 4. Typen, Werte und Variablen “ dargelegt. Die Java-Sprache folgt OOP-Konzepten und unterstützt die Vererbung mithilfe des Schlüsselworts „extens“. Warum Erweiterung? Denn bei der Vererbung erbt eine untergeordnete Klasse das Verhalten und den Zustand der übergeordneten Klasse und kann diese ergänzen, d. h. Erweitern Sie die Funktionalität der Basisklasse. Eine Schnittstelle kann auch in der Klassenbeschreibung mit dem Schlüsselwort „implements“ angegeben werden. Wenn eine Klasse eine Schnittstelle implementiert, bedeutet dies, dass die Klasse einem Vertrag entspricht – einer Erklärung des Programmierers gegenüber dem Rest der Umgebung, dass die Klasse ein bestimmtes Verhalten aufweist. Der Player verfügt beispielsweise über verschiedene Tasten. Diese Schaltflächen sind eine Schnittstelle zur Steuerung des Verhaltens des Players und das Verhalten ändert den internen Zustand des Players (z. B. Lautstärke). In diesem Fall werden der Zustand und das Verhalten als Beschreibung einer Klasse gegeben. Wenn eine Klasse eine Schnittstelle implementiert, kann ein von dieser Klasse erstelltes Objekt nicht nur durch die Klasse, sondern auch durch die Schnittstelle durch einen Typ beschrieben werden. Schauen wir uns ein Beispiel an:
public class MusicPlayer {

    public static interface Device {
        public void turnOn();
        public void turnOff();
    }

    public static class Mp3Player implements Device {
        public void turnOn() {
            System.out.println("On. Ready for mp3.");
        }
        public void turnOff() {
            System.out.println("Off");
        }
    }

    public static class Mp4Player extends Mp3Player {
        @Override
        public void turnOn() {
            System.out.println("On. Ready for mp3/mp4.");
        }
    }

    public static void main(String []args) throws Exception{
        // Какое-то устройство (Тип = Device)
        Device mp3Player = new Mp3Player();
        mp3Player.turnOn();
        // У нас есть mp4 проигрыватель, но нам от него нужно только mp3
        // Пользуемся им Wie mp3 проигрывателем (Тип = Mp3Player)
        Mp3Player mp4Player = new Mp4Player();
        mp4Player.turnOn();
    }
}
Typ ist eine sehr wichtige Beschreibung. Es sagt aus, wie wir mit dem Objekt arbeiten werden, d. h. welches Verhalten wir vom Objekt erwarten. Verhaltensweisen sind Methoden. Lassen Sie uns daher die Methoden verstehen. Auf der Oracle-Website gibt es für Methoden im Oracle-Tutorial einen eigenen Abschnitt: „ Methoden definieren “. Das Erste, was ich aus dem Artikel mitnehmen sollte: Die Signatur einer Methode ist der Name der Methode und die Parametertypen :
Polymorphismus und seine Freunde - 2
Wenn Sie beispielsweise eine Methode als öffentliche void-Methode (Objekt o) deklarieren, besteht die Signatur aus dem Namen der Methode und dem Typ des Parameterobjekts. Der Rückgabetyp ist NICHT in der Signatur enthalten. Es ist wichtig! Als nächstes kompilieren wir unseren Quellcode. Wie wir wissen, muss der Code hierfür in einer Datei mit dem Namen der Klasse und der Erweiterung Java gespeichert werden. Java-Code wird mit dem „ javac “-Compiler in ein Zwischenformat kompiliert , das von der Java Virtual Machine (JVM) ausgeführt werden kann. Dieses Zwischenformat heißt Bytecode und ist in Dateien mit der Erweiterung .class enthalten. Lassen Sie uns den Befehl zum Kompilieren ausführen: javac MusicPlayer.java Nachdem der Java-Code kompiliert wurde, können wir ihn ausführen. Mit dem Dienstprogramm „ java “ wird der Java Virtual Machine-Prozess gestartet, um den in der Klassendatei übergebenen Bytecode auszuführen. Lassen Sie uns den Befehl ausführen, um die Anwendung zu starten: java MusicPlayer. Auf dem Bildschirm sehen wir den Text, der im Eingabeparameter der println-Methode angegeben ist. Wenn wir den Bytecode in einer Datei mit der Erweiterung .class haben, können wir ihn interessanterweise mit dem Dienstprogramm „ javap “ anzeigen. Lassen Sie uns den Befehl <ocde>javap -c MusicPlayer ausführen:
Polymorphismus und seine Freunde - 3
Aus dem Bytecode können wir erkennen, dass der Aufruf einer Methode über ein Objekt, dessen Typ die Klasse angegeben wurde, mit ausgeführt wird invokevirtualund der Compiler berechnet hat, welche Methodensignatur verwendet werden soll. Warum invokevirtual? Weil es einen Aufruf (invoke wird als Aufruf übersetzt) ​​einer virtuellen Methode gibt. Was ist eine virtuelle Methode? Dies ist eine Methode, deren Hauptteil während der Programmausführung überschrieben werden kann. Stellen Sie sich einfach vor, Sie hätten eine Liste der Entsprechungen zwischen einem bestimmten Schlüssel (Methodensignatur) und dem Hauptteil (Code) der Methode. Und diese Entsprechung zwischen dem Schlüssel und dem Hauptteil der Methode kann sich während der Programmausführung ändern. Daher ist die Methode virtuell. Standardmäßig sind in Java Methoden, die NICHT statisch, NICHT endgültig und NICHT privat sind, virtuell. Dadurch unterstützt Java das objektorientierte Programmierprinzip des Polymorphismus. Wie Sie vielleicht bereits verstanden haben, geht es in unserem heutigen Testbericht darum.

Polymorphismus

Auf der Oracle-Website gibt es in ihrem offiziellen Tutorial einen separaten Abschnitt: „ Polymorphismus “. Lassen Sie uns den Java Online Compiler verwenden , um zu sehen, wie Polymorphismus in Java funktioniert. Zum Beispiel haben wir eine abstrakte Klasse Number , die eine Zahl in Java darstellt. Was erlaubt es? Er verfügt über einige grundlegende Techniken, die alle Erben beherrschen werden. Jeder, der von Number erbt, sagt wörtlich: „Ich bin eine Nummer, du kannst mit mir als Nummer arbeiten.“ Beispielsweise können Sie für jeden Nachfolger die Methode intValue() verwenden, um dessen Integer-Wert abzurufen. Wenn Sie sich die Java-API für Number ansehen, können Sie sehen, dass die Methode abstrakt ist, das heißt, jeder Nachfolger von Number muss diese Methode selbst implementieren. Aber was bringt uns das? Schauen wir uns ein Beispiel an:
public class HelloWorld {

    public static int summ(Number first, Number second) {
        return first.intValue() + second.intValue();
    }

    public static void main(String []args){
        System.out.println(summ(1, 2));
        System.out.println(summ(1L, 4L));
        System.out.println(summ(1L, 5));
        System.out.println(summ(1.0, 3));
    }
}
Wie aus dem Beispiel hervorgeht, können wir dank Polymorphismus eine Methode schreiben, die Argumente jeden Typs als Eingabe akzeptiert, die ein Nachkomme von Number sind (wir können Number nicht erhalten, da es sich um eine abstrakte Klasse handelt). Wie im Player-Beispiel sagen wir auch in diesem Fall, dass wir mit etwas wie Number arbeiten wollen. Wir wissen, dass jeder, der eine Zahl ist, in der Lage sein muss, ihren ganzzahligen Wert anzugeben. Und das reicht uns. Wir möchten nicht näher auf die Implementierung eines bestimmten Objekts eingehen und mit diesem Objekt über Methoden arbeiten, die allen Nachkommen von Number gemeinsam sind. Die Liste der Methoden, die uns zur Verfügung stehen, wird zur Kompilierungszeit nach Typ bestimmt (wie wir zuvor im Bytecode gesehen haben). In diesem Fall ist unser Typ „Nummer“. Wie Sie dem Beispiel entnehmen können, übergeben wir unterschiedliche Zahlen unterschiedlicher Typen, d. h. die Summ-Methode erhält Integer, Long und Double als Eingabe. Allen gemeinsam ist jedoch, dass sie Nachkommen der abstrakten Zahl sind und daher ihr Verhalten in der intValue-Methode überschreiben, weil Jeder spezifische Typ weiß, wie er diesen Typ in eine Ganzzahl umwandelt. Ein solcher Polymorphismus wird durch das sogenannte Overriding, im Englischen Overriding, umgesetzt.
Polymorphismus und seine Freunde - 4
Überschreibender oder dynamischer Polymorphismus. Beginnen wir also damit, die Datei HelloWorld.java mit folgendem Inhalt zu speichern:
public class HelloWorld {
    public static class Parent {
        public void method() {
            System.out.println("Parent");
        }
    }
    public static class Child extends Parent {
        public void method() {
            System.out.println("Child");
        }
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();
        parent.method();
        child.method();
    }
}
Lass es uns tun javac HelloWorld.javaund javap -c HelloWorld:
Polymorphismus und seine Freunde – 5
Wie Sie sehen, wird im Bytecode für die Zeilen mit einem Methodenaufruf derselbe Verweis auf die aufzurufende Methode angegeben invokevirtual (#6). Lass es uns tun java HelloWorld. Wie wir sehen können, werden die Variablen „Eltern“ und „Kind“ mit dem Typ „Parent“ deklariert, aber die Implementierung selbst wird abhängig davon aufgerufen, welches Objekt der Variablen zugewiesen wurde (d. h. welcher Objekttyp). Während der Programmausführung (man sagt auch zur Laufzeit) führte die JVM je nach Objekt beim Aufruf von Methoden mit derselben Signatur unterschiedliche Methoden aus. Das heißt, wir haben mit dem Schlüssel der entsprechenden Signatur zuerst einen Methodenkörper und dann einen anderen erhalten. Abhängig davon, welches Objekt in der Variablen enthalten ist. Diese Festlegung zum Zeitpunkt der Programmausführung, welche Methode aufgerufen wird, wird auch als spätes Binden oder dynamisches Binden bezeichnet. Das heißt, der Abgleich zwischen der Signatur und dem Methodenkörper erfolgt dynamisch, abhängig von dem Objekt, für das die Methode aufgerufen wird. Natürlich können Sie statische Mitglieder einer Klasse (Klassenmitglied) sowie Klassenmitglieder mit dem Zugriffstyp private oder final nicht überschreiben. @Override-Anmerkungen helfen Entwicklern ebenfalls. Dies hilft dem Compiler zu verstehen, dass wir an dieser Stelle das Verhalten einer Vorfahrenmethode überschreiben werden. Wenn wir einen Fehler in der Methodensignatur gemacht haben, wird uns der Compiler sofort darüber informieren. Zum Beispiel:
public static class Parent {
        public void method() {
            System.out.println("parent");
        }
}
public static class Child extends Parent {
        @Override
        public void method(String text) {
            System.out.println("child");
        }
}
Kompiliert nicht mit Fehler: Fehler: Methode überschreibt oder implementiert keine Methode aus einem Supertyp
Polymorphismus und seine Freunde - 6
Mit dem Konzept der „ Kovarianz “ ist auch eine Neudefinition verbunden. Schauen wir uns ein Beispiel an:
public class HelloWorld {
    public static class Parent {
        public Number method() {
            return 1;
        }
    }
    public static class Child extends Parent {
        @Override
        public Integer method() {
            return 2;
        }
    }

    public static void main(String[] args) {
        System.out.println(new Child().method());
    }
}
Trotz der scheinbaren Abstrusität besteht die Bedeutung darin, dass wir beim Überschreiben nicht nur den Typ zurückgeben können, der im Vorfahren angegeben wurde, sondern auch einen spezifischeren Typ. Beispielsweise hat der Vorfahr eine Zahl zurückgegeben, und wir können eine Ganzzahl zurückgeben – den Nachkommen von Zahl. Das Gleiche gilt für Ausnahmen, die in den Würfen der Methode deklariert werden. Erben können die Methode überschreiben und die ausgelöste Ausnahme verfeinern. Aber sie können nicht expandieren. Das heißt, wenn das übergeordnete Element eine IOException auslöst, können wir die genauere EOFException auslösen, aber keine Ausnahme. Ebenso wenig können Sie den Geltungsbereich einschränken und keine zusätzlichen Beschränkungen auferlegen. Sie können beispielsweise keine statische Aufladung hinzufügen.
Polymorphismus und seine Freunde – 7

Versteckt

Es gibt auch so etwas wie „ Verheimlichung “. Beispiel:
public class HelloWorld {
    public static class Parent {
        public static void method() {
            System.out.println("Parent");
        }
    }
    public static class Child extends Parent {
        public static void method() {
            System.out.println("Child");
        }
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();
        parent.method();
        child.method();
    }
}
Das ist eine ziemlich offensichtliche Sache, wenn man darüber nachdenkt. Statische Mitglieder einer Klasse gehören zur Klasse, d. h. zum Typ der Variablen. Daher ist es logisch, dass, wenn „child“ vom Typ „Parent“ ist, die Methode für „Parent“ und nicht für „child“ aufgerufen wird. Wenn wir uns wie zuvor den Bytecode ansehen, werden wir sehen, dass die statische Methode mit invokestatic aufgerufen wird. Dies erklärt der JVM, dass sie auf den Typ und nicht auf die Methodentabelle achten muss, wie dies bei invokevirtual oder invokeinterface der Fall war.
Polymorphismus und seine Freunde - 8

Überladungsmethoden

Was sehen wir sonst noch im Java Oracle Tutorial? Im zuvor untersuchten Abschnitt „ Methoden definieren “ geht es um Überladung. Was ist das? Auf Russisch ist das „Methodenüberladung“, und solche Methoden werden „überladen“ genannt. Also Methodenüberladung. Auf den ersten Blick ist alles einfach. Öffnen wir einen Online-Java-Compiler, zum Beispiel „Tutorialspoint Online Java Compiler“ .
public class HelloWorld {

	public static void main(String []args){
		HelloWorld hw = new HelloWorld();
		hw.say(1);
		hw.say("1");
	}

	public static void say(Integer number) {
		System.out.println("Integer " + number);
	}
	public static void say(String number) {
		System.out.println("String " + number);
	}
}
Hier scheint also alles einfach zu sein. Wie im Oracle-Tutorial erwähnt, unterscheiden sich überladene Methoden (in diesem Fall die say-Methode) in der Anzahl und Art der an die Methode übergebenen Argumente. Sie können nicht denselben Namen und dieselbe Anzahl identischer Argumenttypen deklarieren, weil Der Compiler kann sie nicht voneinander unterscheiden. Es lohnt sich, gleich eine sehr wichtige Sache anzumerken:
Polymorphismus und seine Freunde - 9
Das heißt, beim Überladen prüft der Compiler die Richtigkeit. Es ist wichtig. Doch wie stellt der Compiler eigentlich fest, dass eine bestimmte Methode aufgerufen werden muss? Es verwendet die Regel „Die spezifischste Methode“, die in der Java-Sprachspezifikation beschrieben ist: „ 15.12.2.5. Auswahl der spezifischsten Methode “. Um zu demonstrieren, wie es funktioniert, nehmen wir ein Beispiel von Oracle Certified Professional Java Programmer:
public class Overload{
  public void method(Object o) {
    System.out.println("Object");
  }
  public void method(java.io.FileNotFoundException f) {
    System.out.println("FileNotFoundException");
  }
  public void method(java.io.IOException i) {
    System.out.println("IOException");
  }
  public static void main(String args[]) {
    Overload test = new Overload();
    test.method(null);
  }
}
Nehmen Sie ein Beispiel von hier: https://github.com/stokito/OCPJP/blob/master/src/ru/habrahabr/blogs/java/OCPJP1/question1/Overload.j... Wie Sie sehen können, bestehen wir null für die Methode. Der Compiler versucht, den spezifischsten Typ zu ermitteln. Objekt ist nicht geeignet, weil alles ist von ihm geerbt. Fortfahren. Es gibt zwei Klassen von Ausnahmen. Schauen wir uns java.io.IOException an und sehen wir, dass es in „Direct Known Subclasses“ eine FileNotFoundException gibt. Das heißt, es stellt sich heraus, dass FileNotFoundException der spezifischste Typ ist. Daher ist das Ergebnis die Ausgabe der Zeichenfolge „FileNotFoundException“. Wenn wir jedoch IOException durch EOFException ersetzen, stellt sich heraus, dass wir zwei Methoden auf derselben Ebene der Hierarchie im Typbaum haben, d. h. für beide Methoden ist IOException das übergeordnete Element. Der Compiler kann nicht auswählen, welche Methode aufgerufen werden soll, und gibt einen Kompilierungsfehler aus: reference to method is ambiguous. Noch ein Beispiel:
public class Overload{
    public static void method(int... array) {
        System.out.println("1");
    }

    public static void main(String args[]) {
        method(1, 2);
    }
}
Es wird 1 ausgegeben. Hier gibt es keine Fragen. Der Typ int... ist ein vararg https://docs.oracle.com/javase/8/docs/technotes/guides/sprache/varargs.html und ist eigentlich nichts anderes als „syntaktischer Zucker“ und eigentlich ein int. .. Array kann als int[]-Array gelesen werden. Wenn wir nun eine Methode hinzufügen:
public static void method(long a, long b) {
	System.out.println("2");
}
Dann wird nicht 1, sondern 2 angezeigt, weil Wir übergeben zwei Zahlen und zwei Argumente passen besser zusammen als ein Array. Wenn wir eine Methode hinzufügen:
public static void method(Integer a, Integer b) {
	System.out.println("3");
}
Dann sehen wir immer noch 2. Denn in diesem Fall stimmen die Grundelemente genauer überein als das Boxen in Integer. Wenn wir sie jedoch ausführen, method(new Integer(1), new Integer(2));wird 3 ausgegeben. Konstruktoren in Java ähneln Methoden, und da sie auch zum Erhalten einer Signatur verwendet werden können, gelten für sie dieselben Regeln zur „Überladungsauflösung“ wie für überladene Methoden. Die Java-Sprachspezifikation sagt uns dies in „ 8.8.8. Konstruktorüberladung “. Methodenüberladung = frühe Bindung (auch bekannt als statische Bindung) Oft hört man von früher und später Bindung, auch bekannt als statische Bindung oder dynamische Bindung. Der Unterschied zwischen ihnen ist sehr einfach. Früh ist die Kompilierung, spät ist der Moment, in dem das Programm ausgeführt wird. Daher ist die frühe Bindung (statische Bindung) die Bestimmung, welche Methode zur Kompilierungszeit von wem aufgerufen wird. Nun, späte Bindung (dynamische Bindung) ist die Bestimmung, welche Methode direkt zum Zeitpunkt der Programmausführung aufgerufen werden soll. Wie wir zuvor gesehen haben (als wir IOException in EOFException geändert haben), erhalten wir einen Kompilierzeitfehler, wenn wir Methoden überladen, sodass der Compiler nicht verstehen kann, wo welcher Aufruf erfolgen soll: Verweis auf Methode ist mehrdeutig. Das aus dem Englischen übersetzte Wort mehrdeutig bedeutet mehrdeutig oder unsicher, ungenau. Es stellt sich heraus, dass Überlastung eine frühe Bindung ist, weil Die Prüfung wird zur Kompilierzeit durchgeführt. Um unsere Schlussfolgerungen zu bestätigen, öffnen wir die Java-Sprachspezifikation im Kapitel „ 8.4.9. Überladung “:
Polymorphismus und seine Freunde – 10
Es stellt sich heraus, dass während der Kompilierung Informationen über die Typen und die Anzahl der Argumente (die zur Kompilierungszeit verfügbar sind) verwendet werden, um die Signatur der Methode zu bestimmen. Wenn es sich bei der Methode um eine der Methoden des Objekts (d. h. eine Instanzmethode) handelt, wird der tatsächliche Methodenaufruf zur Laufzeit mithilfe der dynamischen Methodensuche (d. h. der dynamischen Bindung) bestimmt. Zur Verdeutlichung nehmen wir ein Beispiel, das dem zuvor besprochenen ähnelt:
public class HelloWorld {
    public void method(int intNumber) {
        System.out.println("intNumber");
    }
    public void method(Integer intNumber) {
        System.out.println("Integer");
    }
    public void method(String intNumber) {
        System.out.println("Number is: " + intNumber);
    }

    public static void main(String args[]) {
        HelloWorld test = new HelloWorld();
        test.method(2);
    }
}
Speichern wir diesen Code in der Datei HelloWorld.java und kompilieren Sie ihn mit. javac HelloWorld.java Sehen wir uns nun an, was unser Compiler in den Bytecode geschrieben hat, indem wir den folgenden Befehl ausführen: javap -verbose HelloWorld.
Polymorphismus und seine Freunde - 11
Wie bereits erwähnt, hat der Compiler festgestellt, dass in Zukunft eine virtuelle Methode aufgerufen wird. Das heißt, der Methodenkörper wird zur Laufzeit definiert. Aber zum Zeitpunkt der Kompilierung wählte der Compiler von allen drei Methoden die am besten geeignete aus und gab daher die Nummer an:"invokevirtual #13"
Polymorphismus und seine Freunde – 12
Was für eine Methode ist das? Dies ist ein Link zur Methode. Grob gesagt ist dies ein Anhaltspunkt, anhand dessen die Java Virtual Machine zur Laufzeit tatsächlich bestimmen kann, nach welcher Methode sie zur Ausführung suchen muss. Weitere Details finden Sie im Superartikel: „ Wie geht JVM mit Methodenüberladung und internem Überschreiben um ?“.

Zusammenfassend

Wir haben also herausgefunden, dass Java als objektorientierte Sprache Polymorphismus unterstützt. Polymorphismus kann statisch (statische Bindung) oder dynamisch (dynamische Bindung) sein. Beim statischen Polymorphismus, auch Early Binding genannt, bestimmt der Compiler, welche Methode wo aufgerufen werden soll. Dies ermöglicht die Verwendung eines Mechanismus wie Überlastung. Beim dynamischen Polymorphismus, auch Late Binding genannt, wird eine Methode basierend auf der zuvor berechneten Signatur einer Methode zur Laufzeit basierend darauf berechnet, welches Objekt verwendet wird (d. h. welche Methode des Objekts aufgerufen wird). Wie diese Mechanismen funktionieren, lässt sich anhand von Bytecode erkennen. Die Überladung prüft die Methodensignaturen und beim Auflösen der Überladung wird die spezifischste (genaueste) Option ausgewählt. Beim Überschreiben wird anhand des Typs ermittelt, welche Methoden verfügbar sind. Die Methoden selbst werden dann basierend auf dem Objekt aufgerufen. Sowie Materialien zum Thema: #Wjatscheslaw
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION