abstract class的特徵:
1. abstract class和abstract method都必須用abstract關鍵字來修飾
2. abstract class不能用new關鍵字去產生物件
3. abstract method只需要宣告, 不需要實作
4. 繼承abstract class的子類別必須實作父類別的abstract method, 否則這子類別還是個abstract class
interface的特徵:
1. interface沒有建構方法 (即method中沒有參數, 且沒有任何變數的設定)
Ex: interface Bus{
void sound();
}
2. interface中所有資料成員都必須初始化, 且均為常數
3. 宣告變數必須是final, static和public
4. interface中的method必須為abstact或public
abstract class 和 interface 的使用時機
何謂abstract class?
提供一種多個class一起合作工作的方式, 將多個class中相同的元素pull up method到public class中, 再以繼承的方式來使用它, 目的是為了實現"多型"精神
Ex: 數學計算包括求各種形狀的面積、體積 、數字的立方、平方等, 就可以把類似的方法集中到同一個public class中
abstract class Shape{
String name;
double length, width, heigh;
double radius;
abstract double area(); // 求面積
abstract double perimeter(); // 求周長
// abstract class中也可以有建構方法, 但必須在子類別中被呼叫
// 四邊形的建構方法
public Shape(double length, double width, String name){
this.length = length;
this.width = width;
this.name = name;
}
// 三角形的建構方法
public Shape(String name, double width, double height){
this.height = height;
this.width = width;
this.name = name;
}
}
class Rectangular extends Shape{ //長方形
public Rectangular(double length, double width, String name){
super(length, width, name); //在子類別中呼叫父類別的
建構方法用super()
}
//因為繼承Shape類別, 因此要實作area和perimeter的abstract class
double area(){
return length * width;
}
double perimeter(){
return (length + width) * 2;
}
}
class EqualTriangle extends Shape{ //三角形
public EqualTrangle(String name, double width, double height){
super(name, width, height);
}
double area(){
return (width * height) / 2 ;
}
double perimeter(){
return 3 * width;
}
}
(註) 一個子類別只能繼承一個父類別, 但一個父類別可以被許多子類別所共同繼承 ---------------------------------------------------------------------------------------------------
何謂interface?
即spec., 完全不需要定義實作, 只需要函式原型
若要實作interface, 就必須follow它的spec.
[public] [abstract] interface 介面名稱{
權限設定 傳回型態 method(parameters);
權限設定 傳回型態 method(parameters);
}
[public] [abstract]是預設, 所以可省略, 因為interface本身就是抽象的
(註)一個介面可以同時繼承多個介面, 即同時繼承了多個介面的abstract method和常數
=> interface A extends 介面1, 介面2, 介面3, ...
一個class可以同時實作多個interface
=> class B implements 介面1, 介面2, 介面3, ...
---------------------------------------------------------------------------------------------------
以另一篇範例來說明, 以下為轉貼自JavaWorld裡avseq的回文
連結在此: http://www.javaworld.com.tw/jute/post/view?bid=29&id=195263
實作時,Interface和Abstract Class的使用時機還蠻難拿捏的
我提供一下我實作時的經驗,如果有可以改進的地方,還希望一起討論
用例子應該比較好了解
本田(Honda)旗下有兩款車,Honda Civic和Honda Accord
這兩款車的輪胎大小,煞車系統,安全氣囊等裝置都一樣,只有引擎的啟動方式不一樣
這時可以定義一個抽象類別HondaCar ,並將引擎啟動的方法定義為abstact,強迫繼承的類別實作這個方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| public abstract class HondaCar { protected int tireSize = 12; protected abstract void engineStart(); protected void stopCar() { // break method } protected void popAirBag() { //pop Air Bag } } |
1
2
3
4
5
6
7
8
9
10
| public class Civic extends HondaCar { protected void engineStart() { // Civic engine start method } } |
1
2
3
4
5
6
7
8
9
10
| public class Accord extends HondaCar { protected void engineStart() { // Accord engine start method } } |
為什麼要定義成抽象類別呢?
1)因為Civic和Accord的特徵幾乎都一樣,只有引擎的啟動方式不同
2)如果不把相同的程式碼定義在上層,這樣一來兩個類別都要寫重覆的程式碼,用複製貼上說不定還會貼錯
3)HondaCar宣告成抽象,是因為它不是一台具體的車,宣告成抽象可以避免這個類別被實體化。
假設現在小日本政府規定,任何車子都要加裝一個裝置,在每1000公里時都要將目前廢氣排放的情況回報給環保署的主機,
至於如何回報?可以WebService連結到環保署的主機,或是寫成一個file ftp到環保署等等..,也就是說,小日本政府不管你回報的方式是什麼就是要回報就對了。
此時可以定義一個interface,讓所有的車子都實作這個介面
1
2
3
4
| public interface CarReporter { public void report(); } |
為什麼現在要用介面呢?
1)介面像是一個規範,所以實作的類別都要遵守這個規範,而不論繼承的類別實作方式是什麼。所以實作CarReporter的車子都有要回報的機制,至於怎麼回報,由各汽車廠自已決定。
2)Civic和Accord,它們的本質是汽車,而繼承關係是(is-a),如果用類別繼承的方式實作的話,會變成Civic是一個排氣回報裝置。所以應該利用實作介面的方式(like-a),也就是說Civic是一台有回報排氣裝置的汽車。
※至於使用時機就看個人的設計了~看看Design Pattern會更清楚有哪些應用,
較複雜一點的Pattern會使用interface + abstract class - "多形" + "繼承"
較複雜一點的Pattern會使用interface + abstract class - "多形" + "繼承"