Heim  >  Artikel  >  Java  >  Detaillierte Einführung und Codebeispiele zu Java-Vererbung, Polymorphismus und Klassenwiederverwendung

Detaillierte Einführung und Codebeispiele zu Java-Vererbung, Polymorphismus und Klassenwiederverwendung

黄舟
黄舟Original
2017-03-14 11:47:342031Durchsuche


Zusammenfassung:
Dieser Artikel kombiniert die Wiederverwendung von Java-Klassen mit den beiden Hauptmerkmalen von objektorientiertVererbung und Polymorphismus werden umfassend vorgestellt. Zunächst stellten wir das Wesen und die Bedeutung der Vererbung vor und untersuchten die Ähnlichkeiten und Unterschiede zwischen Vererbung, Zusammensetzung und Proxy im Hinblick auf die Wiederverwendung von Klassen. Als nächstes führten wir den auf Vererbung basierenden Polymorphismus ein und stellten seinen Implementierungsmechanismus und spezifische Anwendungen vor. Darüber hinaus bieten wir zum besseren Verständnis von Vererbung und Polymorphismus eine umfassende Einführung in das Schlüsselwort final. Auf dieser Grundlage haben wir die Lade- und Initialisierungssequenz von Klassen in Java eingeführt. Abschließend haben wir drei sehr wichtige Konzepte im objektorientierten Design ausführlich erläutert: Überladen, Überschreiben und Ausblenden.


Wichtige Punkte:

  • Vererbung

  • Zusammensetzung, Vererbung, Stellvertreter

  • Polymorphismus

  • letztes Schlüsselwort

  • Klassenlade- und Initialisierungssequenz

  • Überladen, Überschreiben und Ausblenden

1. Vererbung

Vererbung ist ein unverzichtbarer Bestandteil aller OOP-Sprachen. Verwenden Sie >extendsSchlüsselwort repräsentiert die Vererbungsbeziehung. Wenn eine Klasse erstellt wird, wird sie immer geerbt. Wenn die zu erbende Klasse nicht explizit angegeben ist, wird sie immer implizit von der Stammklasse Objekt geerbt. Wenn zwischen zwei Klassen eine Vererbungsbeziehung besteht, erbt die Unterklasse automatisch die Methoden und Variablen der übergeordneten Klasse, und die Methoden und Variablen der übergeordneten Klasse können direkt in der Unterklasse aufgerufen werden. Es sollte darauf hingewiesen werden, dass in Java nur eine einzelne Vererbung erlaubt ist, d. h. eine Klasse kann nur explizit von höchstens einer übergeordneten Klasse erben. Allerdings eine Klasse kann von mehreren Klassen geerbt werden, das heißt, eine Klasse kann mehrere Unterklassen haben. Darüber hinaus müssen wir den folgenden Punkten besondere Aufmerksamkeit schenken:

1.

Vererbung von Mitgliedsvariablen Wenn eine Unterklasse eine bestimmte Klasse erbt, wird sie Es können Mitgliedsvariablen in der übergeordneten Klasse verwendet werden, es werden jedoch nicht alle Mitgliedsvariablen der übergeordneten Klasse vollständig vererbt. Die spezifischen Prinzipien lauten wie folgt:

  • Unterklassen können die öffentlichen und geschützten Mitgliedsvariablen , kann die privaten Mitgliedsvariablen der übergeordneten Klasse nicht erben, kann aber die entsprechende Getter-/Setter-Methode übergeben der übergeordneten Klasse für den Zugriff ; Wenn sich die Unterklasse und die übergeordnete Klasse im selben Paket befinden, kann die Unterklasse nicht erben

  • Für die übergeordnete Klasse, die die Unterklasse erben kann Klassenmitgliedsvariablen,
  • Wenn eine Mitgliedsvariable mit demselben Namen in einer Unterklasse erscheint, wird die Es tritt ein verstecktes -Phänomen auf, das heißt, die Unterklasse Die Mitgliedsvariablen der übergeordneten Klasse blockieren die gleichnamigen Mitgliedsvariablen der übergeordneten Klasse. Wenn Sie in einer Unterklasse auf eine Mitgliedsvariable mit demselben Namen in der übergeordneten Klasse zugreifen möchten, müssen Sie das Schlüsselwort super verwenden, um eine

    Referenz
  • zu erstellen.
  • 2. Vererbung der Mitgliedsmethode Wenn eine Unterklasse eine bestimmte Klasse erbt, kann sie ebenfalls verwendet werden Mitgliedsmethoden in der übergeordneten Klasse, aber die Unterklasse erbt nicht alle Methoden der übergeordneten Klasse vollständig. Die spezifischen Prinzipien lauten wie folgt:

  • Unterklassen können die

öffentlichen und geschützten Mitgliedsmethoden , kann die

  • private Member-Methode

    nicht erben; Für die Paketzugriffsmitgliedsmethoden der übergeordneten Klasse gilt: Wenn sich die Unterklasse und die übergeordnete Klasse im selben Paket befinden, kann die Unterklasse erben, andernfalls kann die Unterklasse nicht erben vererbt werden;

  • Für übergeordnete Klassen-Member-Methoden, die Unterklassen erben können: Wenn eine Member-Methode mit demselben Namen in der Unterklasse erscheint, wird sie genannt überschreibt , das heißt, die Mitgliedsmethoden der Unterklasse überschreiben die gleichnamigen Mitgliedsmethoden der übergeordneten Klasse. Wenn Sie in einer Unterklasse auf eine gleichnamige Mitgliedsmethode in der übergeordneten Klasse zugreifen möchten, müssen Sie das Schlüsselwort super als Referenz verwenden.

Programmbeispiel:

class Person {    
public String gentle = "Father";
}public class Student extends Person {

    public String gentle = "Son";    
    public String print(){        
    return super.gentle;       
    // 在子类中访问父类中同名成员变
    }    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();
        System.out.println("##### " + student.gentle);
        Person p = student;
        System.out.println("***** " + p.gentle);    //隐藏:编译时决定,不会发生多态

        System.out.println("----- " + student.print());
        System.out.println("----- " + p.print());    //Error:Person 中未定义该方法
    }
}/* Output:
        ##### Son
        ***** Father
        ----- Father
 *///:~

 Verstecken und Verdecken sind unterschiedlich. Versteckt ist für Mitgliedsvariablen und statische Methoden , während Überschreibungen gelten gegenüber gewöhnlichen Methoden .


3. Initialisierung und Konstruktor der Basisklasse

Wir wissen, dass eine exportierte Klasse wie eine Basisklasse mit derselben Schnittstelle ist neue Klasse, vielleicht mit einigen zusätzlichen Methoden und Feldern. Bei der Vererbung wird jedoch nicht nur die Schnittstelle der Basisklasse kopiert. Wenn Sie ein abgeleitetes Klassenobjekt erstellen, enthält das Objekt ein untergeordnetes Objekt der Basisklasse. Dieses Unterobjekt ist dasselbe wie das Objekt, das wir direkt mithilfe der Basisklasse erstellen. Der Unterschied zwischen den beiden besteht darin, dass letzteres von außen kommt, während die Unterobjekte der Basisklasse in das abgeleitete Klassenobjekt eingeschlossen sind.
 
Daher ist entscheidend für die korrekte Initialisierung von Unterobjekten der Basisklasse, und Java stellt auch entsprechende Methoden bereit, um dies sicherzustellen: Die abgeleitete Klasse muss Rufen Sie den Basisklassenkonstruktor im Konstruktor auf, um die Initialisierung durchzuführen , und der Basisklassenkonstruktor verfügt über alle Kenntnisse und Fähigkeiten, die zum Durchführen der Basisklasseninitialisierung erforderlich sind. Wenn die Basisklasse einen Standardkonstruktor enthält, fügt Java automatisch einen Aufruf des Standardkonstruktors der Basisklasse in den Konstruktor der abgeleiteten Klasse ein, da der Compiler nicht berücksichtigen muss, welche Parameter übergeben werden sollen. Allerdings Wenn die übergeordnete Klasse keinen Standardkonstruktor enthält oder die abgeleitete Klasse einen übergeordneten Klassenkonstruktor mit Parametern aufrufen möchte, muss das Schlüsselwort super verwendet werden, um ihn explizit im Konstruktor der abgeleiteten Klasse aufzurufen Klasse. Der entsprechende Basisklassenkonstruktor und die aufrufende Anweisung müssen die erste Anweisung des abgeleiteten Klassenkonstruktors sein.


2. Kombination, Vererbung, Proxy

In Java können Kombination, Vererbung und Proxy Code zur Wiederverwendung implementieren.

(1) Zusammensetzung (has-a)

 Durch Hinzufügen der vorhandenen Klasse zur neuen Klasse können Objekte erstellt werden kombiniert werden. Das heißt, die neue Klasse besteht aus Objekten bestehender Klassen. Diese Technik wird normalerweise verwendet, wenn Sie die Funktionalität einer vorhandenen Klasse in einer neuen Klasse anstelle ihrer Schnittstelle verwenden möchten. Mit anderen Worten: Betten Sie ein Objekt in eine neue Klasse ein, damit es die erforderlichen Funktionen erreichen kann, Benutzer der neuen Klasse jedoch nur die für die neue Klasse definierte Schnittstelle sehen die Schnittstelle des eingebetteten Objekts.


(2) Vererbung (is-a)

 Vererbung ermöglicht es uns, eine neue Klasse zu erstellen. Das heißt, wir nehmen die Form einer vorhandenen Klasse an und fügen darin neuen Code hinzu. Normalerweise bedeutet dies, dass wir einen allgemeinen Kurs belegen und ihn auf einen besonderen Bedarf spezialisieren. Im Wesentlichen Sowohl Komposition als auch Vererbung ermöglichen die Platzierung von Unterobjekten in einer neuen Klasse, die Komposition macht dies explizit, während die Vererbung dies implizit tut.


(3) Proxy (ein goldener Mittelwert zwischen Vererbung und Zusammensetzung: Verwenden Sie die Funktionen vorhandener Klassen wie die Zusammensetzung, während Sie sie wie die Vererbungsschnittstelle einer vorhandenen Klasse verwenden)

 Proxy ist eine goldene Mitte zwischen Vererbung und Zusammensetzung, Java bietet keine direkte Unterstützung dafür. In einem Proxy platzieren wir ein Mitgliedsobjekt in der zu erstellenden Klasse (wie Komposition), machen aber gleichzeitig die Schnittstelle/Methoden dieses Mitgliedsobjekts in der neuen Klasse verfügbar (wie Vererbung).
 
Programmbeispiel:

// 控制模块public class SpaceShipControls {
    void up(int velocity) {
    }    void down(int velocity) {
    }    void left(int velocity) {
    }    void right(int velocity) {
    }    void forward(int velocity) {
    }    void back(int velocity) {
    }    void turboBoost() {
    }
}

Das Raumschiff benötigt also ein Steuermodul, Eine Möglichkeit, ein Raumschiff zu strukturieren, ist die Verwendung von Vererbung:

public class SpaceShip extends SpaceShipControls { 
    private String name; 
    public SpaceShip(String name) { this.name = name; } 
    public String toString() { return name; } 
    public static void main(String[] args) { 
        SpaceShip protector = new SpaceShip("NSEA Protector"); 
        protector.forward(100); 
    } 
}

  然而,SpaceShip 并不是真正的 SpaceShipControls 类型,即便你可以“告诉” SpaceShip 向前运动(forward())。更准确的说,SpaceShip 包含 SpaceShipControls ,与此同时, SpaceShipControls 的所有方法在 SpaceShip 中都暴露出来。 代理(SpaceShip 的运动行为由 SpaceShipControls 代理完成) 正好可以解决这种问题:

// SpaceShip 的行为由 SpaceShipControls 代理完成public class SpaceShipDelegation { 
    private String name; 
    private SpaceShipControls controls = new SpaceShipControls(); 

    public SpaceShipDelegation(String name) { 
        this.name = name; 
    } 

    // 代理方法: 
    public void back(int velocity) { 
        controls.back(velocity); 
    } 
    public void down(int velocity) { 
        controls.down(velocity); 
    } 
    public void forward(int velocity) { 
        controls.forward(velocity); 
    } 
    public void left(int velocity) { 
        controls.left(velocity); 
    } 
    public void right(int velocity) { 
        controls.right(velocity); 
    } 
    public void turboBoost() { 
        controls.turboBoost(); 
    } 
    public void up(int velocity) { 
        controls.up(velocity); 
    } 

    public static void main(String[] args) { 
        SpaceShipDelegation protector = new SpaceShipDelegation("NSEA Protector"); 
        protector.forward(100); 
    } 
}

  实际上,我们使用代理时可以拥有更多的控制力,因为我们可以选择只提供在成员对象中方法的某个子集。


三. final关键字

  许多编程语言都需要某种方法来向编译器告知一块数据是恒定不变的。有时,数据的恒定不变是很有用的,比如:

  • 一个永不改变的编译时常量

  • 一个在运行时被初始化的值,而你不希望它被改变。

      对于编译期常量这种情况,编译器可以将该常量值带入任何可能用到它的计算式中,也即是说,可以在编译时执行计算式,这减轻了一些运行时负担。在Java中,这类常量必须满足两个条件:

  • 是基本类型,并且用final修饰;

  • 在对这个常量进行定义的时候,必须对其进行赋值。

      此外,当用final修饰对象引用时,final使其引用恒定不变。一旦引用被初始化指向一个对象,就无法再把它指向另一个对象。然而,对象本身是可以被修改的,这同样适用于数组,因为它也是对象。

      特别需要注意的是,我们不能因为某数据是final的,就认为在编译时就可以知道它的值。例如:

public class Test { 
    final int i4 = rand.nextInt(20);
}

1、空白final

  Java允许生成 空白final , 即:声明final但又未给定初值的域。但无论什么情况,编译器都会确保空白final在使用前被初始化。但是,空白final在关键字final的使用上提供了更大的灵活性: 一个类中的 final域 就可以做到根据对象而有所不同,却又保持其恒定不变的特性。例如,
         blank final.png-58.9kB
         
  必须在域的定义处或者每个构造器中使用表达式对final进行赋值,这正是 final域 在使用前总是被初始化的原因所在。


2、final参数

  final参数 主要应用于局部内部类和匿名内部类中,更多详细介绍请移步我的另一篇文章:Java 内部类综述。


3、final方法

  final关键字作用域方法时,用于锁定方法,以防任何继承类修改它的含义。这是出于设计的考虑:想要确保在继承中使方法行为保持不变,并且不会被覆盖。

  对于成员方法,只有在明确禁止覆盖时,才将方法设为final的。


4、final类

 Wenn Sie eine Klasse als endgültig definieren, bedeutet dies, dass Sie nicht beabsichtigen, die Klasse zu erben, und dass Sie anderen nicht erlauben, dies zu tun. Mit anderen Worten, aus irgendeinem Grund müssen Sie nie Änderungen am Design dieser Klasse vornehmen, oder aus Sicherheitsgründen möchten Sie nicht, dass dies der Fall ist Unterklassen Art.
 
Es ist zu beachten, dass die Felder der Abschlussklasse je nach tatsächlicher Situation wählen können, ob sie endgültig sind. Unabhängig davon, ob es als endgültig definiert ist, gelten für Felder, die als endgültig definiert sind, dieselben Regeln. Allerdings Da finale Klassen die Vererbung verbieten, werden alle Methoden in einer finalen Klasse implizit als final bezeichnet, da sie nicht überschrieben werden können. Sie können den Methoden in einer endgültigen Klasse endgültige Änderungen hinzufügen, dies fügt jedoch keine Bedeutung hinzu.


5. final und privat

 Alle privaten Methoden in der Klasse werden implizit als final bezeichnet. Da auf die private Methode nicht zugegriffen werden kann, kann sie nicht überschrieben werden. Sie können einer privaten Methode eine endgültige Änderung hinzufügen, dies verleiht der Methode jedoch keine zusätzliche Bedeutung.
 
Es ist wichtig zu beachten, dass die Überschreibung nur angezeigt wird, wenn eine Methode Teil der Basisklassenschnittstelle ist. Wenn eine Methode privat ist, ist sie nicht Teil der Basisklassenschnittstelle, sondern lediglich ein in der Klasse versteckter Programmcode. Wenn jedoch in der exportierten Klasse eine nicht private Methode mit demselben Namen generiert wird, überschreiben wir die Methode zu diesem Zeitpunkt nicht, sondern generieren nur eine neue Methode. Da auf die private Methode nicht zugegriffen werden kann und sie effektiv ausgeblendet werden kann, besteht keine Notwendigkeit, sie in einer anderen Situation in Betracht zu ziehen, außer wenn sie aufgrund der Organisationsstruktur der Klasse, zu der sie gehört, vorhanden ist.


6. final und static 🎜>

kann
  • ändern, und sein

    kann nur Mitgliedsvariablen und Mitgliedsmethoden ändern. Ein statisches Endfeld

    belegt nur einen nicht veränderbaren Speicherplatz, und die Initialisierung kann nur zum Zeitpunkt der Deklaration erfolgen
  • .

    Da es endgültig ist, hat es keinen Standardwert und ist statisch. Daher wurde ihm ein Wert zugewiesen, wenn die Klasse nicht instanziiert wurde, sodass es nur initialisiert werden kann, wenn es deklariert wird. IV. Polymorphismus Wir wissen, dass Vererbung es ermöglicht, ein Objekt als seinen eigenen Typ oder seine Basis zu behandeln Typen werden so verarbeitet, dass derselbe Code ohne Unterschied auf diesen verschiedenen Typen ausgeführt werden kann. Unter anderem ermöglichen polymorphe Methodenaufrufe, dass sich ein Typ anders als andere ähnliche Typen verhält, sofern diese Typen von derselben Basisklasse abgeleitet sind. Also,

  • Die Rolle des Polymorphismus spiegelt sich hauptsächlich in zwei Aspekten wider:

Polymorphismus durch Trennung Was zu tun und wie es zu tun ist, trennen Sie die Schnittstelle und die Implementierung aus einer anderen Perspektive, um die geänderten Dinge von den unveränderten Dingen zu trennen

  • Beseitigen Sie die Kopplungsbeziehung zwischen Typen (In ähnlicher Weise werden in Java auch Generika verwendet, um die Kopplungsbeziehung zwischen Klassen oder Methoden und den verwendeten Typen zu beseitigen).

  • 1. Implementierungsmechanismus

    Wir wissen, dass das Überschreiben von Methoden Polymorphismus sehr gut verkörpert, aber welche Methode sollte korrekt aufgerufen werden, wenn eine Basisklassenreferenz zum Aufrufen einer überschreibenden Methode verwendet wird?

    Das Verknüpfen eines Methodenaufrufs mit demselben Methodenkörper wird als Bindung bezeichnet . Wenn die Bindung vor der Programmausführung durchgeführt wird, spricht man von früher Bindung . Dieser Mechanismus kann das obige Problem jedoch offensichtlich nicht lösen, da der Compiler zur Kompilierungszeit nicht weiß, auf welches Objekt die obige Basisklassenreferenz verweist. Die Lösung ist späte Bindung (dynamische Bindung/Laufzeitbindung): Bindung entsprechend dem spezifischen Typ des Objekts zur Laufzeit.

    Tatsächlich sind in Java alle anderen Methoden mit Ausnahme der statischen Methoden und der endgültigen Methoden (private Methoden sind endgültige Methoden) spät bindend. Auf diese Weise kann, nachdem eine Methode als endgültig deklariert wurde, verhindert werden, dass andere die Methode überschreiben, aber was noch wichtiger ist: Dadurch kann die dynamische Bindung effektiv deaktiviert werden, oder mit anderen Worten, dem Compiler mitgeteilt werden, dass dies der Fall ist Die dynamische Bindung muss nicht geändert werden, um effizienteren Code für endgültige Methodenaufrufe zu generieren.

    Basierend auf dem dynamischen Bindungsmechanismus können wir Code schreiben, der sich nur mit Basisklassen befasst, und diese Codes können für alle exportierten Klassen korrekt ausgeführt werden. Mit anderen Worten: Senden Sie eine Nachricht an ein Objekt und lassen Sie das Objekt entscheiden, was zu tun ist.


    2. Downcasting und Laufzeittypidentifikation

    Da beim Upcasting bestimmte Typinformationen verloren gehen, denken wir vielleicht, dass es auch möglich sein sollte, diese zu erhalten Geben Sie Informationen über Downcasting ein. Wir wissen jedoch, dass Upcasting sicher ist, da die Basisklasse keine größere Schnittstelle als die abgeleitete Klasse hat. Daher können die Nachrichten, die wir über die Basisklassenschnittstelle senden, akzeptiert werden, für die Abwärtstransformation können wir dies jedoch nicht garantieren.

    Um dieses Problem zu lösen, muss es eine Möglichkeit geben, die Richtigkeit der Abwärtsumwandlung sicherzustellen, damit wir nicht vorschnell in einen falschen Typ umwandeln und dann eine Nachricht senden, die das Objekt nicht akzeptieren kann. In Java kann der Runtime Type Identification (RTTI)-Mechanismus dieses Problem lösen, der sicherstellt, dass alle Transformationen in Java überprüft werden. Selbst wenn wir also nur eine gewöhnliche Typkonvertierung in Klammern durchführen, wird diese beim Aufrufen der Laufzeit dennoch überprüft, um sicherzustellen, dass es sich tatsächlich um den gewünschten Typ handelt. Wenn nicht, erhalten wir eine Typkonvertierungsausnahme: ClassCastException.


    3. Beispiele für polymorphe Anwendungen

    Das heißt, initialisieren Sie zuerst die statischen Mitgliedsvariablen und statischen Codeblöcke in der übergeordneten Klasse in der Reihenfolge, in der sie im Programm erscheinen, und initialisieren Sie dann die statischen Mitgliedsvariablen und statischen Codeblöcke in Initialisieren Sie die Unterklasse in der Reihenfolge, in der sie im Programm erscheinen. Zweitens werden die gewöhnlichen Mitgliedsvariablen und Codeblöcke der übergeordneten Klasse initialisiert. Anschließend wird die
    -Konstruktionsmethode der übergeordneten Klasse initialisiert Mitgliedsvariablen und Codeblöcke der Unterklasse und führen Sie dann die Konstruktionsmethode der Unterklasse aus.

    Wir erklären es mit folgendem Programm:

    class SuperClass {    private static String STR = "Super Class Static Variable";    static {
            System.out.println("Super Class Static Block:" + STR);
        }    public SuperClass() {
            System.out.println("Super Class Constructor Method");
        }
    
        {
            System.out.println("Super Class Block");
        }
    
    }public class ObjectInit extends SuperClass {
        private static String STR = "Class Static Variable";    static {
            System.out.println("Class Static Block:" + STR);
        }    public ObjectInit() {
            System.out.println("Constructor Method");
        }
    
        {
            System.out.println("Class Block");
        }    public static void main(String[] args) {        @SuppressWarnings("unused")
            ObjectInit a = new ObjectInit();
        }
    }/* Output:
            Super Class Static Block:Super Class Static Variable
            Class Static Block:Class Static Variable
            Super Class Block
            Super Class Constructor Method
            Class Block
            Constructor Method
     *///:~

      在运行该程序时,所发生的第一件事就是试图访问 ObjectInit.main() 方法(一个static方法),于是加载器开始启动并加载 ObjectInit类 。在对其加载时,编译器注意到它有一个基类(这由关键字extends得知),于是先进行加载其基类。如果该基类还有其自身的基类,那么先加载这个父父基类,如此类推(本例中是先加载 Object类 ,再加载 SuperClass类 ,最后加载 ObjectInit类 )。接下来,根基类中的 static域 和 static代码块 会被执行,然后是下一个导出类,以此类推这种方式很重要,因为导出类的static初始化可能会依赖于基类成员能否被正确初始化。到此为止,所有的类都已加载完毕,对象就可以创建了。首先,初始化根基类所有的普通成员变量和代码块,然后执行根基类构造器以便创建一个基对象,然后是下一个导出类,依次类推,直到初始化完成。


    六. 重载、覆盖与隐藏

    1、重载与覆盖

    (1) 定义与区别

      重载如果在一个类中定义了多个同名的方法,但它们有不同的参数(包含三方面:参数个数、参数类型和参数顺序),则称为方法的重载。其中,不能通过访问权限、返回类型和抛出异常进行重载。
       
      覆盖子类中定义的某个方法与其父类中某个方法具有相同的方法签名(包含相同的名称和参数列表),则称为方法的覆盖。子类对象使用这个方法时,将调用该方法在子类中的定义,对它而言,父类中该方法的定义被屏蔽了。

      总的来说,重载和覆盖是Java多态性的不同表现。前者是一个类中多态性的一种表现,后者是父类与子类之间多态性的一种表现。


    (2) 实现机制

      重载是一种参数多态机制,即通过方法参数的差异实现多态机制。并且,其属于一种 静态绑定机制,在编译时已经知道具体执行哪个方法。
       
      覆盖是一种动态绑定的多态机制。即,在父类与子类中具有相同签名的方法具有不同的具体实现,至于最终执行哪个方法 根据运行时的实际情况而定。


    (3) 总结

      我们应该注意以下几点:

    • final 方法不能被覆盖;

    • 子类不能覆盖父类的private方法,否则,只是在子类中定义了一个与父类重名的全新的方法,而不会有任何覆盖效果。

        其他需要注意的地方如下图所示:

               Detaillierte Einführung und Codebeispiele zu Java-Vererbung, Polymorphismus und Klassenwiederverwendung


    2、覆盖与隐藏

    (1) 定义

    覆盖:指 运行时系统调用当前对象引用 运行时类型 中定义的方法 ,属于 运行期绑定。

    隐藏:指运行时系统调用当前对象引用 编译时类型 中定义的方法,即 被声明或者转换为什么类型就调用对应类型中的方法或变量,属于编译期绑定。


    (2) 范围

    Überschreiben: nur für Instanzmethoden
    Ausblenden :Nur ​​für statische Methoden und Mitgliedsvariablen.


    (3) Zusammenfassung

    • Die Instanzmethode der Unterklasse kann die statische Methode der übergeordneten Klasse nicht verbergen, da sonst ein Kompilierungsfehler auftritt 🎜>

    • Sowohl statische Mitglieder als auch Instanzmitglieder können durch gleichnamige Mitgliedsvariablen in Unterklassen ausgeblendet werden.

      Das folgende Programmbeispiel veranschaulicht die drei Konzepte des Überladens, Überschreibens und Ausblendens gut:    
      Detaillierte Einführung und Codebeispiele zu Java-Vererbung, Polymorphismus und Klassenwiederverwendung

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung und Codebeispiele zu Java-Vererbung, Polymorphismus und Klassenwiederverwendung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn