在本教程中,我們將借助示例學(xué)習(xí)Java中的繼承。
繼承是OOP(面向?qū)ο缶幊蹋┑闹匾δ苤?,它使我們能夠從現(xiàn)有類中定義一個新類。例如,
class Animal { // eat() 方法 // sleep() 方法 } class Dog extends Animal { // bark() 方法 }
在Java中,我們使用extends關(guān)鍵字從類繼承。在這里,我們從Animal類繼承了Dog類。
Animal是超類(父類或基類),而Dog是子類(子類或派生類)。 子類繼承超類的字段和方法。
繼承是is-a關(guān)系,只有當(dāng)兩個類之間存在is-a關(guān)系時,我們才使用繼承。
這里有些實例:
汽車就是車輛。
橙色是一種水果。
外科醫(yī)生是醫(yī)生。
狗是動物。
class Animal { public void eat() { System.out.println("I can eat"); } public void sleep() { System.out.println("I can sleep"); } } class Dog extends Animal { public void bark() { System.out.println("I can bark"); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.eat(); dog1.sleep(); dog1.bark(); } }
輸出結(jié)果
I can eat I can sleep I can bark
在這里,我們從父類Animal繼承了Dog的子類。 Dog類從Animal類繼承了eat()和sleep()方法。
因此,Dog類的對象可以訪問Dog類和Animal類的成員。
我們在先前的教程中了解了private和public訪問修飾符。
private 成員只能在類內(nèi)訪問
public 成員可以從任何地方訪問
您還可以設(shè)置方法和字段為protected,受保護(hù)的成員可以訪問
類內(nèi)部
在其子類中
在同一包內(nèi)
這是可以訪問訪問修飾符的摘要。
修飾符 | 類 | 包 | 子類 | 全局 |
---|---|---|---|---|
public | Yes | Yes | Yes | Yes |
private | Yes | No | No | No |
protected | Yes | Yes | Yes | No |
class Animal { protected String type; private String color; public void eat() { System.out.println("I can eat"); } public void sleep() { System.out.println("I can sleep"); } public String getColor(){ return color; } public void setColor(String col){ color = col; } } class Dog extends Animal { public void displayInfo(String c){ System.out.println("I am a " + type); System.out.println("My color is " + c); } public void bark() { System.out.println("I can bark"); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.eat(); dog1.sleep(); dog1.bark(); dog1.type = "mammal"; dog1.setColor("black"); dog1.displayInfo(dog1.getColor()); } }
輸出結(jié)果
I can eat I can sleep I can bark I am a mammal My color is black
在這里,Animal類中的類型字段受到保護(hù)。我們已經(jīng)從Main類訪問了這個字段
dog1.type = "mammal";
這是可行的,因為Animal和Main類都在同一個包(同一個文件)中。
從上面的示例中,我們知道子類的對象也可以訪問其超類的方法。
如果在超類和子類中都定義了相同的方法,會發(fā)生什么情況?
好吧,在這種情況下,子類中的方法將覆蓋超類中的方法。例如,
class Animal { protected String type = "animal"; public void eat() { System.out.println("I can eat"); } public void sleep() { System.out.println("I can sleep"); } } class Dog extends Animal { @Override public void eat() { System.out.println("I eat dog food"); } public void bark() { System.out.println("I can bark"); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.eat(); dog1.sleep(); dog1.bark(); } }
輸出結(jié)果
I eat dog food I can sleep I can bark
在這里,eat()同時出現(xiàn)在超類Animal和子類Dog中。我們創(chuàng)建了子類Dog的對象dog1。
當(dāng)我們使用dog1對象調(diào)用eat()時,將調(diào)用Dog內(nèi)部的方法,而不調(diào)用超類的相同方法。這稱為方法重寫。
在上面的程序中,我們使用了@Override 注釋來告訴編譯器我們正在重寫方法。但是,這不是強(qiáng)制性的。在下一個教程中,我們將詳細(xì)了解方法重寫。
如果需要從Animal的子類調(diào)用eat()方法,則使用super關(guān)鍵字。
class Animal { public Animal() { System.out.println("I am an Animal"); } public void eat() { System.out.println("I can eat"); } } class Dog extends Animal { public Dog(){ super(); System.out.println("I am a dog"); } @Override public void eat() { super.eat(); System.out.println("I eat dog food"); } public void bark() { System.out.println("I can bark"); } } class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.eat(); dog1.bark(); } }
輸出結(jié)果
I am an Animal I am a dog I can eat I eat dog food I can bark
在這里,我們使用了super關(guān)鍵字通過super()來調(diào)用構(gòu)造函數(shù)。 另外,我們使用super.eat()調(diào)用Animal超類的eat()方法。
注意:調(diào)用構(gòu)造函數(shù)和super方法時使用的區(qū)別。要了解更多信息,請訪問Java super關(guān)鍵字。
繼承有五種類型。
單一繼承 - B類A僅從類繼承。
多級繼承 - B類從A類繼承,然后C類從B類繼承。
分層繼承 - A類作為B,C和D父類。
多重繼承 -類C從接口A和擴(kuò)展B。
混合繼承 -兩種或多種繼承的混合。
Java不支持通過類的多重繼承和混合繼承。但是,我們可以通過接口在Java中實現(xiàn)多重繼承。我們將在后面的章節(jié)中了解接口。
最重要的用途是代碼的可重用性。父類中存在的代碼無需在子類中再次編寫。
通過方法重寫實現(xiàn)運(yùn)行時多態(tài)。在后面的章節(jié)中,我們將學(xué)習(xí)有關(guān)多態(tài)的更多信息。