Wie wird Java-Polymorphismus implementiert?
Polymorphismus wird in Java wie in C++ durch spätes Binden oder Laufzeitbinden erreicht. Wenn eine von einem Objekt referenzierte Methode aufgerufen wird, weiß der Compiler nicht, ob die Referenz auf das Typobjekt verweist, das bei der Deklaration der Variablen angegeben wurde, oder auf ein Objekt einer Unterklasse des Typs. Daher kann der Compiler für diesen Aufruf keine Bindung an eine bestimmte Methode durchführen. Es kann zur Laufzeit nur über die Laufzeittypidentifikation (RTTI) in Java an eine bestimmte Methode gebunden werden. Das Folgende ist ein konkretes Beispiel:
class shape { public void draw() { print("shape"); } } class triangle extends shape { public void draw() { print("triangle"); } } public class Polymorphism { public static void main(String[] args) { shape s=new triangle(); s.draw(); }
Das Ergebnis ist, dass Triangle
s eine Formreferenz ist, aber zur Laufzeit wird die Zeichenmethode von Triangle immer noch aufgerufen, da es sich um ein Dreiecksobjekt handelt.
Einige Fallstricke beim Java-Polymorphismus
Private Methoden überschreiben?
Private Methoden können in Java nicht überschrieben werden. Dies ist eigentlich leicht zu verstehen, da private Methoden in Unterklassen nicht sichtbar sind. Unterklassen erben nicht die privaten Methoden der übergeordneten Klasse, geschweige denn überschreiben sie diese. Daher ist die gleichnamige Methode in der Unterklasse eine völlig neue Methode.
public class Polymorphism { private void show() { print("show parent"); } public static void main(String[] args) { Polymorphism p=new privateMethod(); p.show(); } } class privateMethod extends Polymorphism { public void show() { print("show derived"); } }
Das Ergebnis ist Polymorphismus von Show-Parent
Feldern und statischen Methoden?
Eine Unterklasse kann die nichtprivaten Felder der übergeordneten Klasse erben. Sind die Felder der Unterklasse auch polymorph? Schauen wir uns ein praktisches Beispiel an:
class shape { protected int perimeter=1; public void draw() { print("shape"); } public int getPerimeter() { return perimeter; } } class triangle extends shape { int perimeter=3; public void draw() { print("triangle"); } public int getPerimeter() { return perimeter; } public int getSuperPerimeter() { return super.perimeter; } } public class Polymorphism { public static void main(String[] args) { shape s=new triangle(); print("s.perimeter:"+s.perimeter); print("s.getperimeter:"+s.getPerimeter()); triangle t=new triangle(); print("t.perimeter:"+t.perimeter); print("t.getperimeter:"+t.getPerimeter()); print("t.getsuperperimeter:"+t.getSuperPerimeter()); } }
Dieses Operationsergebnis enthält die folgenden Informationen:
1 Nachdem das Dreiecksobjekt in eine Form umgewandelt wurde, wird der direkte Zugriff auf die Felder bestimmt Compiler, daher ist dies nicht der Fall. Es zeigt Polymorphismus und gibt 1 zurück.
2. Nachdem das Dreiecksobjekt in die Form umgewandelt wurde, wird die Methode zum Zugriff auf das Feld aufgerufen. Die getperimeter-Methode des Dreiecks wird entsprechend der Verzögerungsbindung des Laufzeitobjekts aufgerufen und der zurückgegebene Wert ist 3.
3.t-Objekt enthält zwei Perimeter, eines stammt von sich selbst und eines stammt von seiner übergeordneten Klasse. Wenn das Feld mit dem Feldnamen aufgerufen wird, wird gleichzeitig standardmäßig sein eigenes Perimeterfeld zurückgegeben. Um das von der übergeordneten Klasse geerbte Feld aufzurufen, verwenden Sie die Methode super.perimeter.
Um diese Situation zu vermeiden, deklarieren wir die Felder im Allgemeinen als privat (Unterklassen können nicht erben). Gleichzeitig ist es am besten, Felder nicht mit demselben Namen wie ein Feld zu deklarieren Von der übergeordneten Klasse geerbt.
Statische Methoden weisen keinen Polymorphismus auf, da statische Methoden an Klassen gebunden sind und es nicht erforderlich ist, den spezifischen Typ zu kennen.
Polymorphismus des Konstruktors?
Der Konstruktor weist keinen Polymorphismus auf, da die Konstruktionsmethode selbst eine statische Methode ist (wenn nicht, fällt sie in einen Henne-Ei-, Eier-Lege-Hühner-Zyklus). Um unser Problem vorzustellen, schauen wir uns zunächst die Reihenfolge an, in der der Konstruktor aufgerufen wird.
1. Der für dieses Objekt zugewiesene Speicherplatz wird auf 0 initialisiert (das Objekt wird auf Null initialisiert)
2. Der Konstruktor der übergeordneten Klasse wird aufgerufen (dies stellt sicher, dass auf die Felder im Konstruktor der Unterklasse zugegriffen wird werden initialisiert)
3. Initialisierung der Mitgliedsvariablen
4. Nehmen wir nun an, dass wir im zweiten Schritt eine bestimmte Methode im Konstruktor der übergeordneten Klasse aufrufen Methode polymorph? Schauen wir uns ein konkretes Beispiel an:
class shape { protected int perimeter=1; public shape() { draw(); print("shape created"); } public void draw() { print("draw shape "+perimeter); } } class triangle extends shape { int perimeter=3; public triangle() { print("triangle created"); } public void draw() { print("draw triangle "+perimeter); } public int getPerimeter() { return perimeter; } } public class Polymorphism { public static void main(String[] args) { shape s=new triangle(); } }
Das Ergebnis ist, dass wir auf die Felder im Dreiecksobjekt zugreifen, bevor es initialisiert wird. Daher müssen wir in tatsächlichen Anwendungen den Aufruf anderer Methoden im Konstruktor vermeiden oder nur private Methoden aufrufen (die nicht vererbt werden, sodass dieses Problem nicht auftritt).
Weitere Vorsichtsmaßnahmen für die Verwendung von Java-Polymorphismus sind damit verbunden. Bitte zahlen Sie Beachten Sie die chinesische PHP-Website für Artikel!