1. 程式人生 > 實用技巧 >java面向物件(下)-- 抽象類與介面

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  }

抽象類和介面的區別

總結:

  1. 抽象類和介面都不能直接例項化,如果要例項化,抽象類變數必須指向實現所有抽象方法的子類物件,介面變數必須指向實現所有介面方法的類物件。
  2. 抽象類要被子類繼承,介面要被類實現。
  3. 抽象類裡可以沒有抽象方法
  4. 類可以不實現抽象類和介面宣告的所有方法,當然,在這種情況下,類也必須得宣告成是抽象的。
  5. 抽象類可以在不提供介面方法實現的情況下實現介面。
  6. Java介面中宣告的變數預設都是final的。抽象類可以包含非final的變數。
  7. Java介面中的成員函式預設是public的。抽象類的成員函式可以是private,protected或者是public。
  8. 介面是絕對抽象的,不可以被例項化,抽象類也不可以被例項化
  9. 一個類實現介面的話要實現介面的所有方法,而抽象類不一定
  10. 類可以實現很多個介面,但是隻能繼承一個抽象類
  11. 介面中沒有this指標,沒有建構函式,不能擁有例項欄位(例項變數)或例項方法。

一句話總結:

從設計層面來說,抽象是對類的抽象,是一種模板設計,介面是行為的抽象,是一種行為的規範。

ps:若理解有誤,請諒解!