抽象類這個概念應該並不陌生,
但實際上這兩個的差異似乎又說不上來,
最近剛好有朋友問到這個部分,
索性就把自己研究的心得分享一下。
程式面的差異
在abstract class中,由於可以繼承的關係,你當然可設定任何作用域的成員變數,
也可以寫abstract和非abstract的方法,差異只是繼承的類必須實作abstract的方法,
非abstract的方法會直接繼承,或者子類可以改寫。
而interface中,你只能實作,想當然你的成員變數一定是public的,
實作interface的類也不能出現重複的屬性,所以interface的屬性也一定是static & final的,
interface中的方法一定是abstract的,實作的類也一定要實作該方法。
概念的差異
在JAVA中只能單一繼承,但是可以實作多個介面,
抽象類可以定義自己的屬性和方法和抽象方法,
從繼承的角度上很容易將子類和其繼承的抽象類聯想為is a的關係,
而類別實作介面時也必須同時實作其中的抽象方法,
介面也並無強調和其實作類的關係,
因此你可以想像成是like a的關係。
實例比較
下面我用一個簡單的例子說明兩者使用的時機和差異性,
如果有發現錯誤或改正的地方煩請不吝指教,
假設我們現在要設計一個抽象的類別 - 車,
車有兩個基本的方法是加速 speed() 和剎車 stop(),
以abstract class的方式定義如下:
public abstract class Car{ abstract void speed(); abstract void stop(); }
以interface的方式定義如下:
public interface Car{ void speed(); void stop(); }
表面上看起來差異不大,
但如果今天要增加一個新的功能叫倒車顯影 backView(),
如果你加在abstract class內,
public abstract class Car{ abstract void speed(); abstract void stop(); abstract void backView(); }
問題來了,那是不是所有繼承車的子類都要實作這個方法,
而且難道所有車的子類,所有廠牌的車子都有倒車顯影嗎??
想必不是,那如果放在interface呢??
public interface Car{ void speed(); void stop(); void backView(); }
道理一樣,原本實作car的類也全部被強制要實作 backView(),
想必這也是不合理的,以下的方式比較正確:
public abstract class Car{ abstract void speed(); abstract void stop(); } public interface BackView{ void backView(); } public class Toyota extends Car implements BackView{ public void backView() {} void speed() {} void stop() {} }
Toyota的本質概念上是一種車,而具有倒車顯影的功能,
從這裡判斷 is a 和 like a 應該很好理解了。
沒有留言:
張貼留言