在本教程中,我們將借助示例來學(xué)習(xí)Java中的方法重寫。
在上一教程中,我們了解了繼承。繼承是一個OOP屬性,它使我們可以從現(xiàn)有的類(父類)派生一個新的類(子類),而子類繼承超類的屬性和方法。
現(xiàn)在,如果在父類和子類中都定義了相同的方法,則子類的方法將覆蓋超類的方法。這稱為方法覆蓋(方法重寫)。
class Animal { public void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { @Override public void displayInfo() { System.out.println("I am a dog."); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
輸出:
I am a dog.
在以上程序中,displayInfo()方法同時存在于Animal父類和Dog子類中。
當(dāng)我們使用d1對象(子類的對象)調(diào)用displayInfo()時,會調(diào)用子類Dog中的方法。子類的displayInfo()方法覆蓋父類的相同方法。
注意在我們的示例中使用了@Override注釋。在Java中,注釋是我們用來向編譯器提供信息的元數(shù)據(jù)。這里,@Override注釋告訴編譯器,該注釋之后的方法將覆蓋超類的方法。
使用@Override不是強(qiáng)制性的。但是,當(dāng)我們使用這個方法時,該方法應(yīng)該遵循覆蓋的所有規(guī)則。否則,編譯器將生成錯誤。
父類和子類都必須具有相同的方法名稱,相同的返回類型和相同的參數(shù)列表。
我們不能重寫聲明為final和static的方法。
我們應(yīng)該始終重寫超類的抽象方法(將在以后的教程中進(jìn)行討論)。
在Java中執(zhí)行重寫時出現(xiàn)的一個常見問題是:
我們可以在重寫后訪問超類的方法嗎?
答案是肯定的。要從子類訪問超類的方法,我們使用super關(guān)鍵字。
class Animal { public void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { public void displayInfo() { super.displayInfo(); System.out.println("I am a dog."); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
輸出:
I am an animal. I am a dog.
在上面的實(shí)例中,子類Dog覆蓋了超類Animal的displayInfo()方法。
當(dāng)我們使用Dog子類的d1對象調(diào)用displayInfo()方法時,將調(diào)用Dog子類內(nèi)部的方法。 不會調(diào)用父類內(nèi)部的方法。
在Dog子類的displayInfo()內(nèi)部,我們使用了super.displayInfo()來調(diào)用父類的displayInfo()。
需要注意的是,Java中的構(gòu)造函數(shù)不會被繼承。因此,在Java中不存在諸如構(gòu)造函數(shù)重寫之類的問題。
但是,我們可以從其子類中調(diào)用超類的構(gòu)造函數(shù)。為此,我們使用super()。要了解更多信息,請?jiān)L問Java super關(guān)鍵字。
在父類及其子類中聲明的相同方法可以具有不同的訪問說明符。但是,有一個限制。
我們只能,在提供比父類的訪問說明符更大的訪問權(quán)限的子類中使用的那些訪問說明符。 例如,
假設(shè)父類中的方法myClass()被聲明為protected。然后,myClass()子類中的相同方法可以是 public 或 protected,但不能是private。
class Animal { protected void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { public void displayInfo() { System.out.println("I am a dog."); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
輸出:
I am a dog.
在上面的示例中,子類Dog重寫了父類Animal的displayInfo()方法。
每當(dāng)我們使用d1(子類的對象)調(diào)用displayInfo()時,就會調(diào)用子類內(nèi)部的方法。
注意,displayInfo()在Animal父類中聲明為受保護(hù)的(protected)。該方法在Dog子類中具有公共訪問說明符(public)。這是允許的,因?yàn)閜ublic提供了比protected更大的訪問權(quán)限。
在Java中,抽象類被創(chuàng)建為其他類的父類(基類)。而且,如果類包含抽象方法,則必須重寫它。
在后面的教程中,我們將學(xué)習(xí)有關(guān)抽象類和抽象方法的重寫的更多信息。