java面向物件(下)-- 抽象類與介面
抽象類
在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類。
抽象類除了不能例項化物件之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣。
由於抽象類不能例項化物件,所以抽象類必須被繼承,才能被使用。也是因為這個原因,通常在設計階段決定要不要設計抽象類。
父類包含了子類集合的常見的方法,但是由於父類本身是抽象的,所以不能使用這些方法。
在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。
抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
當一個類中包含了抽象方法,該類必須使用abstract關鍵字來修飾,使用abstract關鍵字來修飾的類被稱為抽象類
1 //定義抽象類Animal類 2 abstract class Animal { 3 //定義抽象方法shout(),沒有方法體 4 abstract void shout(); 5 } 6 //定義Dog類繼承抽象類Animal類 7 class Dog extends Animal{ 8 //實現抽象方法 9 @Override 10 void shout() { 11 System.out.println("汪汪汪....");12 } 13 } 14 15 //定義測試類 16 class Example { 17 public static void main(String[] args) { 18 Dog dog = new Dog(); //例項化Dog物件 19 dog.shout(); 20 } 21 }
執行結果:
抽象類總結規定
-
抽象類不能被例項化(也就是說抽象類生來註定是被繼承的,否則定義抽象類就沒有意義),如果被例項化,就會報錯,編譯無法通過。只有抽象類的非抽象子類可以建立物件。
-
抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
-
抽象類中的抽象方法只是宣告,不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。
-
構造方法,類方法(用 static 修飾的方法)不能宣告為抽象方法。
-
抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。
介面
如果抽象類中的所有方法都是抽象的,則可以將這個類用另一種方式來定義,即介面。
介面(英文:Interface),在JAVA程式語言中是一個抽象型別,是抽象方法的集合,介面通常以interface來宣告。一個類通過繼承介面的方式,從而來繼承介面的抽象方法。
介面並不是類,編寫介面的方式和類很相似,但是它們屬於不同的概念。類描述物件的屬性和方法。介面則包含類要實現的方法。
除非實現介面的類是抽象類,否則該類要定義介面中的所有方法。
介面無法被例項化,但是可以被實現。一個實現介面的類,必須實現介面內所描述的所有方法,否則就必須宣告為抽象類。另外,在 Java 中,介面型別可用來宣告一個變數,他們可以成為一個空指標,或是被繫結在一個以此介面實現的物件。
介面特性
- 介面中每一個方法也是隱式抽象的,介面中的方法會被隱式的指定為public abstract(只能是 public abstract,其他修飾符都會報錯)。
- 介面中可以含有變數,但是介面中的變數會被隱式的指定為public static final變數(並且只能是 public,用 private 修飾會報編譯錯誤)。
- 介面中的方法是不能在介面中實現的,只能由實現介面的類來實現介面中的方法。
介面的宣告
介面的宣告語法格式如下:
介面的實現
由於介面中的方法都是抽象方法,因此不能提供例項化物件的方式來呼叫介面中的方法。此時需要定義一個類,並使用implements關鍵字來實現介面中的所有方法。
當類實現介面的時候,類要實現介面中所有的方法。否則,類必須宣告為抽象的類。
- 介面是隱式抽象的,當宣告一個介面的時候,不必使用abstract關鍵字。
- 介面中每一個方法也是隱式抽象的,宣告時同樣不需要abstract關鍵字。
- 介面中的方法都是公有的。
1 //定義了介面Animal 2 interface Animal { 3 int Id = 1;//定義全域性變數 4 void breathe();//定義抽象方法breathe() 5 void run(); //定義抽象方法run() 6 } 7 //定義Dog類實現了Animal介面 8 class Dog implements Animal{ 9 10 //實現breathe()方法 11 public void breathe() { 12 System.out.println("狗在吐舌頭!"); 13 } 14 15 //實現run()方法 16 public void run() { 17 System.out.println("狗在奔跑!"); 18 } 19 } 20 //定義測試類 21 class Example { 22 public static void main(String[] args) { 23 Dog dog = new Dog(); //例項化Dog物件 24 dog.breathe(); //呼叫Dog類的breathe()方法 25 dog.run();//呼叫Dog類的run()方法 26 } 27 }
執行結果:
重寫介面中宣告的方法時,需要注意以下規則:
- 類在實現介面的方法時,不能丟擲強制性異常,只能在介面中,或者繼承介面的抽象類中丟擲該強制性異常。
- 類在重寫方法時要保持一致的方法名,並且應該保持相同或者相相容的返回值型別。
- 如果實現介面的類是抽象類,那麼就沒必要實現該介面的所有方法。
介面的特點
-
一個介面能繼承另一個(或多個)介面,這和類之間的繼承比較相似。
-
一個類可以同時實現多個介面。
-
一個類繼承另一個類時還可以實現介面。
一個介面能繼承另一個介面,和類之間的繼承方式比較相似。介面的繼承使用extends關鍵字,子介面繼承父介面的方法。
1 //定義了介面Animal 2 interface Animal { 3 int Id = 1;//定義全域性變數 4 void breathe();//定義抽象方法breathe() 5 void run(); //定義抽象方法run() 6 } 7 //定義了LandAnimal介面並繼承了Animal介面 8 interface LandAnimal extends Animal{ //介面繼承介面 9 void liveOnland(); //定義了程式抽象方法 10 } 11 //定義Dog類實現了LandAnimal介面 12 class Dog implements LandAnimal{ 13 14 //實現breathe()方法 15 public void breathe() { 16 System.out.println("狗在吐舌頭!"); 17 } 18 19 //實現run()方法 20 public void run() { 21 System.out.println("狗在奔跑!"); 22 } 23 24 //實現liveOnland()方法 25 public void liveOnland() { 26 System.out.println("狗生活在陸地上"); 27 } 28 } 29 //定義測試類 30 class Example { 31 public static void main(String[] args) { 32 Dog dog = new Dog(); //例項化Dog物件 33 dog.breathe(); //呼叫Dog類的breathe()方法 34 dog.run();//呼叫Dog類的run()方法 35 dog.liveOnland();//呼叫Dog類的liveOnland()方法 36 } 37 }
執行結果:
定義了兩個介面,其中LandAnimal 繼承了Animal介面,因此LandAnimal介面包含了三個抽象方法;當Dog實現了LandAnimal介面時,需要實現兩個介面中的三個方法。
也可以通過extends關鍵字繼承多個介面,多個介面之間用逗號隔開
1 interface 介面1{ 2 程式程式碼···· 3 } 4 interface 介面2{ 5 程式程式碼···· 6 } 7 interface 介面3 extends 介面1,介面2{ 8 程式程式碼···· 9 }
一個類通過implements關鍵字實現介面時,可以實現多個介面,被多個介面之間用逗號隔開
1 interface 介面1{ 2 程式程式碼···· 3 } 4 interface 介面2{ 5 程式程式碼···· 6 } 7 class 類名 implements 介面1,介面2{ 8 程式程式碼···· 9 } 10
一個來在繼承另一個類的同時還可以實現介面,此時,extends關鍵字必須位於implements關鍵字之前。
1 class 類名 extends 父類 implements 介面{ 2 程式程式碼···· 3 }
抽象類和介面的區別
總結:
- 抽象類和介面都不能直接例項化,如果要例項化,抽象類變數必須指向實現所有抽象方法的子類物件,介面變數必須指向實現所有介面方法的類物件。
- 抽象類要被子類繼承,介面要被類實現。
- 抽象類裡可以沒有抽象方法
- 類可以不實現抽象類和介面宣告的所有方法,當然,在這種情況下,類也必須得宣告成是抽象的。
- 抽象類可以在不提供介面方法實現的情況下實現介面。
- Java介面中宣告的變數預設都是final的。抽象類可以包含非final的變數。
- Java介面中的成員函式預設是public的。抽象類的成員函式可以是private,protected或者是public。
- 介面是絕對抽象的,不可以被例項化,抽象類也不可以被例項化。
- 一個類實現介面的話要實現介面的所有方法,而抽象類不一定
- 類可以實現很多個介面,但是隻能繼承一個抽象類
- 介面中沒有
this
指標,沒有建構函式,不能擁有例項欄位(例項變數)或例項方法。
一句話總結:
從設計層面來說,抽象是對類的抽象,是一種模板設計,介面是行為的抽象,是一種行為的規範。
ps:若理解有誤,請諒解!