在本教程中,我們將學(xué)習(xí)Java中的抽象。我們將學(xué)習(xí)Java抽象類和方法,以及如何在程序中使用它們。
抽象類是無法實(shí)例化的類(我們無法創(chuàng)建抽象類的對象)。在Java中,我們使用abstract關(guān)鍵字聲明一個(gè)抽象類。
abstract class Animal { //屬性和方法 }
如果嘗試創(chuàng)建抽象類的對象,則會出現(xiàn)編譯錯(cuò)誤。例如,
Animal a1 = new Animal()
它將產(chǎn)生一個(gè)編譯錯(cuò)誤:
Animal is abstract; cannot be instantiated
盡管不能實(shí)例化抽象類,但是我們可以從中創(chuàng)建子類。我們可以創(chuàng)建子類的對象來訪問抽象類的成員。
在詳細(xì)了解它之前,我們需要了解抽象方法。
我們使用相同的關(guān)鍵字abstract來創(chuàng)建抽象方法。聲明了一個(gè)抽象方法而沒有實(shí)現(xiàn)。例如,
abstract void makeSound();
在這里,makeSound()是一種抽象方法。
重要的是要注意,只有一個(gè)抽象類才能包含抽象方法。如果我們在不是抽象的類中包含抽象方法,則會出現(xiàn)錯(cuò)誤。抽象類可以包含抽象方法和非抽象方法。這是一個(gè)實(shí)例。
abstract class Animal { public void displayInfo() { System.out.println(“I am an animal.”); } abstract void makeSound(); }
在上面的示例中,我們創(chuàng)建了一個(gè)抽象類Animal。它包含一個(gè)抽象方法makeSound()和一個(gè)非抽象方法displayInfo()。
抽象類無法實(shí)例化。要訪問抽象類的成員,我們必須繼承它。例如
abstract class Animal { public void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
輸出:
I am an animal.
在上面的示例中,我們創(chuàng)建了一個(gè)抽象類Animal。我們不能創(chuàng)建Animal類的對象。為了訪問Animal類中的displayInfo()方法,我們繼承了Animal的子類Dog。
然后,我們使用Dog的d1對象訪問該displayInfo()方法。
在Java中,必須在子類中重寫超類的抽象方法。這是因?yàn)樽宇惱^承了超類的抽象方法。
因?yàn)槲覀兊淖宇惏橄蠓椒?,所以我們需要重寫它們?
注意:如果子類也被聲明為抽象,則不必強(qiáng)制重寫抽象方法。
abstract class Animal { abstract void makeSound(); public void eat() { System.out.println("I can eat."); } } class Dog extends Animal { public void makeSound() { System.out.println("Bark bark"); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.makeSound(); d1.eat(); } }
輸出:
Bark bark. I can eat.
在上面的示例中,我們創(chuàng)建了一個(gè)抽象類Animal。該類包含一個(gè)抽象方法makeSound()和一個(gè)非抽象方法eat()。
我們從超類Animal繼承了一個(gè)子類Dog。這里,子類Dog覆蓋了抽象方法displayInfo()。
然后我們創(chuàng)建了Dog的對象d1。使用該對象,我們調(diào)用了d1.displayInfo()和d1.eat()方法。
與非抽象類相似,我們使用super關(guān)鍵字從子類訪問抽象類的構(gòu)造函數(shù)。例如,
abstract class Animal { Animal() { …. } } class Dog extends Animal { Dog() { super(); ... } }
在這里,我們使用Dog的構(gòu)造函數(shù)中的super()訪問Animal類的構(gòu)造函數(shù)。
注意,super 始終應(yīng)是子類構(gòu)造函數(shù)的第一條語句。訪問Java超級關(guān)鍵字以了解更多信息。
抽象是面向?qū)ο缶幊痰闹匾拍?。抽象僅顯示所需的信息,所有不必要的細(xì)節(jié)都保持隱藏。這使我們能夠通過使用更簡單,更高級的想法省略或隱藏細(xì)節(jié)來管理復(fù)雜性。
抽象的實(shí)際示例可以是摩托車制動器。我們知道剎車的作用。當(dāng)我們踩剎車時(shí),摩托車將停止。但是,制動器的工作對我們而言是隱藏的。
隱藏制動器工作原理的主要優(yōu)點(diǎn)是,現(xiàn)在制造商可以為不同的摩托車使用不同的制動器,但是制動器的作用是相同的。
讓我們舉一個(gè)實(shí)例來幫助我們更好地理解Java抽象。
abstract class Animal { abstract void makeSound(); } class Dog extends Animal { public void makeSound() { System.out.println("Bark bark."); } } class Cat extends Animal { public void makeSound() { System.out.println("Meows "); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.makeSound(); Cat c1 = new Cat(); c1.makeSound(); } }
輸出:
Bark bark Meows
在上面的示例中,我們創(chuàng)建了一個(gè)超類Animal。超類Animal具有抽象方法makeSound()。
makeSound()方法無法在Animal內(nèi)部實(shí)現(xiàn)。這是因?yàn)槊糠N動物都會發(fā)出不同的聲音。因此,Animal的所有子類都有不同的makeSound()實(shí)現(xiàn)方法。
我們不能以對Animal的所有子類都正確的方式在Animal中實(shí)現(xiàn)makeSound()。 因此,Animal中makeSound()的實(shí)現(xiàn)保持隱藏狀態(tài)。
在上面的示例中,Dog實(shí)現(xiàn)了它自己的makeSound()實(shí)現(xiàn),Cat實(shí)現(xiàn)了自己的makeSound()。
我們使用abstract關(guān)鍵字來創(chuàng)建抽象類和方法。
抽象方法沒有任何實(shí)現(xiàn)(方法體)。
包含抽象方法的類也應(yīng)該是抽象的。
我們不能創(chuàng)建抽象類的對象。
為了實(shí)現(xiàn)抽象類的功能,我們從其繼承子類并創(chuàng)建該子類的對象。
子類必須重寫抽象類的所有抽象方法。但是,如果子類被聲明為抽象的,則不必強(qiáng)制重寫抽象方法。
我們可以使用抽象類的引用來訪問抽象類的靜態(tài)屬性和方法。例如,
Animal.staticMethod();
在Java中,接口類似于抽象類。但是,接口沒有任何非抽象方法。在下一個(gè)教程中,我們將學(xué)習(xí)有關(guān)接口的更多信息。