重寫和隱藏方法 實(shí)例方法
子類中的實(shí)例方法的簽名(名稱,加上其參數(shù)的數(shù)量和類型)和返回類型與超類中的實(shí)例方法相同,將覆蓋超類的方法。
子類覆蓋方法的能力允許類從行為“足夠接近”的超類繼承,然后根據(jù)需要修改行為,重寫方法與它重寫的方法具有相同的名稱、數(shù)量和參數(shù)類型,以及返回類型。重寫方法還可以返回由被重寫方法返回的類型的子類型,此子類型稱為協(xié)變返回類型。
覆蓋方法時,你可能希望使用@Override注解來指示編譯器你要覆蓋超類中的方法,如果由于某種原因,編譯器檢測到該方法在其中一個超類中不存在,那么它將生成錯誤,有關(guān)@Override的更多信息,請參閱注解。
靜態(tài)方法如果子類定義的靜態(tài)方法與超類中的靜態(tài)方法具有相同的簽名,則子類中的方法會隱藏超類中的方法。
隱藏靜態(tài)方法和覆蓋實(shí)例方法之間的區(qū)別具有重要意義:
被調(diào)用的重寫的實(shí)例方法的版本是子類中的版本。
被調(diào)用的隱藏靜態(tài)方法的版本取決于它是從超類還是從子類調(diào)用的。
考慮一個包含兩個類的示例,第一個是Animal,它包含一個實(shí)例方法和一個靜態(tài)方法:
public class Animal { public static void testClassMethod() { System.out.println("The static method in Animal"); } public void testInstanceMethod() { System.out.println("The instance method in Animal"); } }
第二個類是Animal的一個子類,叫做Cat:
public class Cat extends Animal { public static void testClassMethod() { System.out.println("The static method in Cat"); } public void testInstanceMethod() { System.out.println("The instance method in Cat"); } public static void main(String[] args) { Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); myAnimal.testInstanceMethod(); } }
Cat類重寫Animal中的實(shí)例方法,并隱藏Animal中的靜態(tài)方法,此類中的main方法創(chuàng)建Cat的實(shí)例,并在類上調(diào)用testClassMethod()并在實(shí)例上調(diào)用testInstanceMethod()。
該程序的輸出如下:
The static method in Animal The instance method in Cat
正如所承諾的那樣,被調(diào)用的隱藏靜態(tài)方法的版本是超類中的版本,被調(diào)用的重寫實(shí)例方法的版本是子類中的版本。
接口方法接口中的默認(rèn)方法和抽象方法與實(shí)例方法一樣是繼承的,但是,當(dāng)類或接口的超類型提供具有相同簽名的多個默認(rèn)方法時,Java編譯器遵循繼承規(guī)則來解決名稱沖突,這些規(guī)則由以下兩個原則驅(qū)動:
實(shí)例方法優(yōu)先于接口默認(rèn)方法。
考慮以下類和接口:
public class Horse { public String identifyMyself() { return "I am a horse."; } } public interface Flyer { default public String identifyMyself() { return "I am able to fly."; } } public interface Mythical { default public String identifyMyself() { return "I am a mythical creature."; } } public class Pegasus extends Horse implements Flyer, Mythical { public static void main(String... args) { Pegasus myApp = new Pegasus(); System.out.println(myApp.identifyMyself()); } }
方法Pegasus.identifyMyself返回字符串I am a horse。
已經(jīng)被其他候選者覆蓋的方法將被忽略,當(dāng)超類型共享一個共同的祖先時,就會出現(xiàn)這種情況。
考慮以下接口和類:
public interface Animal { default public String identifyMyself() { return "I am an animal."; } } public interface EggLayer extends Animal { default public String identifyMyself() { return "I am able to lay eggs."; } } public interface FireBreather extends Animal { } public class Dragon implements EggLayer, FireBreather { public static void main (String... args) { Dragon myApp = new Dragon(); System.out.println(myApp.identifyMyself()); } }
方法Dragon.identifyMyself返回字符串I am able to lay eggs。
如果兩個或多個獨(dú)立定義的默認(rèn)方法沖突,或者默認(rèn)方法與抽象方法沖突,則Java編譯器會產(chǎn)生編譯器錯誤,你必須顯式覆蓋超類型方法。
考慮一下現(xiàn)在可以飛行的計算機(jī)控制汽車的例子,你有兩個接口(OperateCar和FlyCar)為同一方法提供默認(rèn)實(shí)現(xiàn)(startEngine):
public interface OperateCar { // ... default public int startEngine(EncryptedKey key) { // Implementation } } public interface FlyCar { // ... default public int startEngine(EncryptedKey key) { // Implementation } }
實(shí)現(xiàn)OperateCar和FlyCar的類必須覆蓋方法startEngine,你可以使用super關(guān)鍵字調(diào)用任何默認(rèn)實(shí)現(xiàn)。
public class FlyingCar implements OperateCar, FlyCar { // ... public int startEngine(EncryptedKey key) { FlyCar.super.startEngine(key); OperateCar.super.startEngine(key); } }
super之前的名稱(在此示例中為FlyCar或OperateCar)必須引用定義或繼承默認(rèn)調(diào)用方法的直接超接口,這種形式的方法調(diào)用不限于區(qū)分包含具有相同簽名的默認(rèn)方法的多個已實(shí)現(xiàn)接口,你可以使用super關(guān)鍵字在類和接口中調(diào)用默認(rèn)方法。
類中的繼承實(shí)例方法可以覆蓋抽象接口方法,考慮以下接口和類:
public interface Mammal { String identifyMyself(); } public class Horse { public String identifyMyself() { return "I am a horse."; } } public class Mustang extends Horse implements Mammal { public static void main(String... args) { Mustang myApp = new Mustang(); System.out.println(myApp.identifyMyself()); } }
方法Mustang.identifyMyself返回字符串I am a horse,Mustang類繼承了Horse類中的方法identifyMyself,它覆蓋了Mammal接口中同名的抽象方法。
注意:接口中的靜態(tài)方法永遠(yuǎn)不會被繼承。修飾符
重寫方法的修飾符可以允許比被重寫方法更多但不是更少的訪問,例如,超類中的protected實(shí)例方法可以在子類中是public,但不能是private。
如果嘗試將超類中的實(shí)例方法更改為子類中的靜態(tài)方法,則會出現(xiàn)編譯時錯誤,反之亦然。
總結(jié)下表總結(jié)了在定義具有與超類中的方法相同的簽名的方法時發(fā)生的情況。
超類實(shí)例方法 | 超類靜態(tài)方法 | |
---|---|---|
子類實(shí)例方法 | 覆蓋 | 生成編譯時錯誤 |
子類靜態(tài)方法 | 生成編譯時錯誤 | 隱藏 |
注意:在子類中,你可以重載從超類繼承的方法,這樣的重載方法既不隱藏也不覆蓋超類實(shí)例方法 — 它們是新方法,對于子類是唯一的。上一篇:繼承 下一篇:多態(tài)性
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72877.html
繼承 在前面的課程中,你已經(jīng)多次看到了繼承,在Java語言中,類可以從其他類派生,從而從這些類繼承字段和方法。 定義:從另一個類派生的類稱為子類(也是派生類,擴(kuò)展類或子類),派生子類的類稱為超類(也是基類或父類)。 除了Object沒有超類,每個類都有一個且只有一個直接超類(單繼承),在沒有任何其他顯式超類的情況下,每個類都隱式地是Object的子類。 類可以從派生自類的類派生的類派生,依此類推,...
使用super關(guān)鍵字 訪問超類成員 如果你的方法覆蓋了它的一個超類的方法,你可以通過使用關(guān)鍵字super來調(diào)用被重寫的方法,你也可以使用super來引用隱藏字段(盡管不鼓勵隱藏字段),慮這個類,Superclass: public class Superclass { public void printMethod() { System.out.println(Print...
多態(tài)性 多態(tài)性的字典定義是指生物學(xué)中的原理,其中生物體或物種可以具有許多不同的形式或階段,這個原則也可以應(yīng)用于面向?qū)ο蟮木幊毯拖馢ava語言之類的語言,類的子類可以定義它們自己的唯一行為,但仍然共享父類的一些相同功能。 可以通過對Bicycle類的微小修改來演示多態(tài)性,例如,可以將printDescription方法添加到顯示當(dāng)前存儲在實(shí)例中的所有數(shù)據(jù)的類中。 public void printD...
Java? 教程 Java教程是為JDK 8編寫的,本頁面中描述的示例和實(shí)踐沒有利用在后續(xù)版本中引入的改進(jìn)。 Java教程是希望使用Java編程語言創(chuàng)建應(yīng)用程序的程序員的實(shí)用指南,其中包括數(shù)百個完整的工作示例和數(shù)十個課程,相關(guān)課程組被組織成教程。 覆蓋基礎(chǔ)知識的路徑 這些教程以書籍的形式提供,如Java教程,第六版,前往Amazon.com購買。 入門 介紹Java技術(shù)和安裝Java開發(fā)軟件并使用...
摘要:抽象數(shù)據(jù)類型的多個不同表示可以共存于同一個程序中,作為實(shí)現(xiàn)接口的不同類。封裝和信息隱藏信息隱藏將精心設(shè)計的模塊與不好的模塊區(qū)分開來的唯一最重要的因素是其隱藏內(nèi)部數(shù)據(jù)和其他模塊的其他實(shí)施細(xì)節(jié)的程度。 大綱 面向?qū)ο蟮臉?biāo)準(zhǔn)基本概念:對象,類,屬性,方法和接口OOP的獨(dú)特功能 封裝和信息隱藏 繼承和重寫 多態(tài)性,子類型和重載 靜態(tài)與動態(tài)分派 Java中一些重要的Object方法設(shè)計好的類面向...
閱讀 3785·2021-08-30 09:47
閱讀 3728·2019-08-30 15:56
閱讀 688·2019-08-30 14:18
閱讀 707·2019-08-29 16:17
閱讀 2077·2019-08-29 11:07
閱讀 654·2019-08-26 13:53
閱讀 3461·2019-08-26 10:26
閱讀 2505·2019-08-23 18:30