Java初探:介面(interface)之繼承與實作

Java不像C++擁有多重繼承的能力,而多重繼承也不見得是一件好事,往往讓事情複雜化。但是,有很多時刻我們會需要使用多重繼承來設計我們所看到的東西,舉例來說:超人=人+超凡能力,在這樣的情況下你就需要多重繼承。

介面的產生就是為了不能夠多重的繼承某一個類別而出現,介面的概念有一點像是在制定一個標準,類似在規劃思考時期時留下的規範。承超人這個例子,你就好好的定義「人」這個介面,只要是人就會作OO,再去好好的定義「超凡能力」這個介面,只要是超凡能力泛指會作XX的動作,這樣一來,你就可以好好的操控你的類别去「實作」(implements)這些介面啦!

介面之宣告、資料成員與方法成員

  1. 介面基本上就是抽象的一種形態,因此宣告時加與不加abstract關鍵字都可以,但是一定要加上interface關鍵字。
  2. 所有介面裡面的資料成員,一律都是public static final,因此一旦宣告就必須馬上給定值。
  3. 所有介面裡面的方法成員,一律都是public abstract,且因為是abstract,所以結尾一定要加上分號。

介面與類別之間的關係##

  1. 一個介面,可以繼承(extends)多個介面。
  2. 一個類別,可以實作(implements)多個介面。
  3. 一個類別,只可以繼承(extends)一個類別
  4. 介面永遠不可能被實例化(instances),你只能去實作(implements)它。
  5. 類別只能繼承(extends)類別,介面只能繼承介面。

下面,我們來實作介面多重繼承介面,並套用到類別實作的範例。

//動物介面 IAnimal.java
public interface IAnimal
{
  //資料成員一定是public、static、final(一定要一開始就給值)
  public String Name = "Animal";  //只要是動物,都會有名字
}

※ 當在別的類别實作IAnimal介面時,你甚至可以使用IAnimal.Name直接取用"Animal"這個字串,因為所有介面中的資料成員,都是static修飾詞,所以可以直接取用!也因為這個特性,因此在實作覆寫(Overridding)時要特別小心。

//人類介面 IPeople.java
public interface IPeople
{
  public int Age = 0;  //只要是人都有年紀
  //方法成員一定是public、abstract(不可以被預設寫入任何程式碼)
  public String Talk();  //只要是人都會講話
}
//嬰兒介面 IBaby.java
public interface IBaby extends IAnimal, IPeople
{
  //嬰兒繼承了動物跟人類
  public boolean Cry();  //只要是嬰兒都會哭
}
//新生兒類別 NewBorn.java 實作 IBaby
public class NewBorn implements IBaby
{
  public int Age = 1;  //出生就算1歲,將0歲洗掉
  public String Name = "Human";  //將預設值"Animal"洗掉
  
  public boolean Cry()
  {
    return true;  //新生兒都會哭
  }
  
  public String Talk()
  {
    return "BraBra...";  //新生兒講話不清楚
  }
  
  public static void main(String[] args)
  {
    NewBorn oTemp = new NewBorn();
    System.out.println(oTemp.Name);  //Human
    System.out.println(oTemp.Age);  //1
    System.out.println(oTemp.Cry());  //true
    System.out.println(oTemp.Talk());  //BraBra...
    //由於NewBorn物件已經沒存取限制,因此可以任意覆寫資料成員
    oTemp.Age = 2;
    oTemp.Name = "John";  
    System.out.println(oTemp.Name);  //John
    System.out.println(oTemp.Age);  //2
  }
}

當然,如果你嫌麻煩的話,也可以直接實現「一個類別,可以實作(implements)多個介面。」這句話,也就是說你可以少寫IBaby.java這個介面,直接把類別改成這樣也是可以完全相容的,怎麼做就見人見智了。感覺我們省掉了一個介面的撰寫時間,但是另外一方面,我們也失去了IBaby介面的完整視別度(規範),從下面的例子我們可以發現,Cry()方法彷彿橫空出世的蹦出來,假設NewBorn跟Cry的關係很不絕對的情況下,這在大型專案的維護上是很傷腦筋的。

public class NewBorn implements IAnimal, IPeople
{
  public int Age = 1;
  public String Name = "Human";
  
  public String Talk()
  {
    return "BraBra...";
  }
  
  //因為已經沒有IBaby介面來規範了,而下方的main又要存取到Cry()這個方法
  //所以Cry在這裡相當於NewBorn自己新增的方法成員
  public boolean Cry()
  {
    return true;
  }
  
  public static void main(String[] args)
  {
    NewBorn oTemp = new NewBorn();
    System.out.println(oTemp.Name);
    System.out.println(oTemp.Age);
    System.out.println(oTemp.Cry());
    System.out.println(oTemp.Talk());
    oTemp.Age = 2;
    oTemp.Name = "John";    
    System.out.println(oTemp.Name);
    System.out.println(oTemp.Age);
  }
}
Java SCJP Class Multi Interfaces Extends