更新時(shí)間:2023-05-16 來(lái)源:黑馬程序員 瀏覽量:
在Java中,abstract class和interface都是用來(lái)定義抽象類(lèi)型的關(guān)鍵字,但它們?cè)谡Z(yǔ)法上有幾個(gè)重要的區(qū)別:
abstract class是一種類(lèi),可以定義構(gòu)造函數(shù)、成員變量和非抽象方法,也可以包含抽象方法,而interface只能定義常量和抽象方法,不能包含任何具體的實(shí)現(xiàn)。
一個(gè)類(lèi)可以繼承多個(gè)接口,但只能繼承一個(gè)抽象類(lèi)。此外,抽象類(lèi)可以作為其他類(lèi)的基類(lèi),而接口不能。
在抽象類(lèi)中可以定義抽象方法,它們必須在非抽象子類(lèi)中實(shí)現(xiàn)。在接口中定義的所有方法都是抽象的,實(shí)現(xiàn)接口的類(lèi)必須提供方法的實(shí)現(xiàn)。
從Java 8開(kāi)始,接口可以定義默認(rèn)方法,這些方法具有默認(rèn)實(shí)現(xiàn),可以被實(shí)現(xiàn)接口的類(lèi)直接繼承或覆蓋。抽象類(lèi)也可以定義具有默認(rèn)實(shí)現(xiàn)的方法,但是默認(rèn)實(shí)現(xiàn)必須是非抽象的。
在抽象類(lèi)中可以定義非常量成員變量,而在接口中只能定義常量(static final)變量。
接下來(lái),筆者用一段Java代碼來(lái)詳細(xì)演示下abstract class和interface之間的語(yǔ)法區(qū)別:
// 抽象類(lèi) abstract class Animal { String name; public Animal(String name) { this.name = name; } // 抽象方法,必須在非抽象子類(lèi)中實(shí)現(xiàn) abstract void makeSound(); // 非抽象方法,可以在抽象類(lèi)中直接實(shí)現(xiàn) public void sleep() { System.out.println(name + " is sleeping."); } } // 接口 interface Swimable { // 常量 int MAX_SPEED = 10; // 抽象方法 void swim(); } // 實(shí)現(xiàn)接口的類(lèi) class Fish implements Swimable { // 必須實(shí)現(xiàn)接口中定義的所有方法 public void swim() { System.out.println("Fish is swimming."); } } // 繼承抽象類(lèi)的子類(lèi) class Dog extends Animal { public Dog(String name) { super(name); } // 必須實(shí)現(xiàn)父類(lèi)中定義的抽象方法 void makeSound() { System.out.println(name + " is barking."); } } public class Main { public static void main(String[] args) { Animal animal = new Dog("Puppy"); animal.makeSound(); animal.sleep(); Swimable swimable = new Fish(); swimable.swim(); System.out.println("Max speed: " + Swimable.MAX_SPEED); } }
在這個(gè)例子中,Animal是一個(gè)抽象類(lèi),它有一個(gè)非抽象方法sleep和一個(gè)抽象方法makeSound。Swimable是一個(gè)接口,它定義了一個(gè)常量MAX_SPEED和一個(gè)抽象方法swim。Fish實(shí)現(xiàn)了Swimable接口,并提供了swim方法的具體實(shí)現(xiàn)。Dog是Animal的子類(lèi),它實(shí)現(xiàn)了makeSound方法,并繼承了sleep方法。在Main類(lèi)中,我們創(chuàng)建了一個(gè)Dog對(duì)象和一個(gè)Fish對(duì)象,并調(diào)用了它們的方法。注意到在Swimable.MAX_SPEED這一行,我們直接通過(guò)接口名訪問(wèn)了接口中定義的常量。