Java初探:介面(interface)之繼承與實作
Java不像C++擁有多重繼承的能力,而多重繼承也不見得是一件好事,往往讓事情複雜化。但是,有很多時刻我們會需要使用多重繼承來設計我們所看到的東西,舉例來說:超人=人+超凡能力,在這樣的情況下你就需要多重繼承。
介面的產生就是為了不能夠多重的繼承某一個類別而出現,介面的概念有一點像是在制定一個標準,類似在規劃思考時期時留下的規範。承超人這個例子,你就好好的定義「人」這個介面,只要是人就會作OO,再去好好的定義「超凡能力」這個介面,只要是超凡能力泛指會作XX的動作,這樣一來,你就可以好好的操控你的類别去「實作」(implements)這些介面啦!
介面之宣告、資料成員與方法成員
- 介面基本上就是抽象的一種形態,因此宣告時加與不加abstract關鍵字都可以,但是一定要加上interface關鍵字。
- 所有介面裡面的資料成員,一律都是public static final,因此一旦宣告就必須馬上給定值。
- 所有介面裡面的方法成員,一律都是public abstract,且因為是abstract,所以結尾一定要加上分號。
介面與類別之間的關係##
- 一個介面,可以繼承(extends)多個介面。
- 一個類別,可以實作(implements)多個介面。
- 一個類別,只可以繼承(extends)一個類別
- 介面永遠不可能被實例化(instances),你只能去實作(implements)它。
- 類別只能繼承(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);
}
}