物件導向中的介面與抽象類別是什麼 ?
介面 (Interface) 與 抽象類別 (Abstract Class) 可以說是在運用多型時必需要知道的程式設計概念。另外在面向介面程式設計與各種設計模式中也會常常被使用到。
介面可以被理解為「接口」,讓外部可以透過這個接口與內部作溝通。
而「接口」通常都是有著某些特定形態的,只有收發雙方都有一樣的「接口」,接口才能被有效使用。
介面作為接口,規範了方法能被外部使用的規則。今天我們會以 USB 來作為大多電腦設備的接口,就是因為 USB 作為一種介面,為我們規範了每台電腦都有一致的接口規格,讓其他週邊產品生產商,能以 USB 介面作為一個標準的接口來進行研發,而不是每個裝置都有不同的傳輸接口。這有助我們消除每台電腦因有不一樣的傳輸接口所導致的不一致問題。
在程式設計中,我們可以透過介面來設定我們想被外部使用的規則,一是可以為每個需要的類別設定一樣的規則,二是避免把不應公開的內部程式碼對外公開。
介面的方法都是抽像 (abstract) 且公開 (public) 的,即介面本身不實作方法,而且為了被外部使用,方法都必定是公開的。
interface USB { public void execute(); public void stop(); }
以下是一個類別實作 (implements) USB 介面的方式,介面中的所有方法都必需要被實作。亦即表示,介面變成了類別的規範。
Class Mouse implements USB { private String state; private int countClick; public void execute() { this.state = "start"; } public void stop() { this.state = "stop"; } private void countClicking() { this.countClick += 1 } }
只要我們的類別需要用到 USB,我們就可以把 USB 介面實作到類別中。當介面作出改動時,所有實作該介面的類別都會收到訊息,以保實所有實作介面的類別都合符介面提出的規範。
但我們要注意的是,介面不一定是要能被重複使用的。換句話說,不是必需要可以被用在多個類別上時我們才使用介面,即使每個類別都有屬於自已的介面也是可以的,重點在於不要過度設計,不要創造出自己也不知道有什麼作用的程式。
抽象類別 (Abstract Class) 是很容易與介面搞混的概念,但他們其實是有很大的不同。抽像類別是不能直接實例化的類別。抽像類型的每個實例都是某個具體子類型的實例。一個抽象類可以提供沒有實現,或不完整的實現。
如果我們說類別是某一種實體,如汽車 ( Car )。那抽象類別就是某一種實體的概念,如抽象車 (AbstractCar) 這個概念。以下可以看到,抽象類別可以實作屬性,亦可先宣告屬性再讓子類來實作或覆寫。抽象類別同時亦可以作類似介面的事情,定下抽象方法,再讓子類別來實現。
abstract Class AbstractCar { private int numberOfWheel = 4; protected String powerUnit; protected abstract void start(); protected abstract String setPowerUnit(); private void printPowerUnit() { print(setPowerUnit()); } }
以上是一個抽象車類別,它先定義車子的 numberOfWheel,再有一個可以被子類別定義的 engineUnit,最後是一個抽象方法 engineStart()。抽象方法不會在抽象類別中被實現,只能於繼承抽象類別的子類別上進行實作。但抽象方法可以被抽象類別中其他程式所調用,達到注入的效果。
Class Car extends AbstractCar{ private String fuelType = ["92", "95, "98"]; protected void start() { driver.turnOn().motor; print("Car Started"); } protected String setPowerUnit() { return "motor" } }
抽象車是我們讓汽車繼承的類別,但是不是也可以給馬車繼承?
Class Carriage extends AbstractCar{ private String fuelType = ["horse"]; protected void start() { driver.whip().horse; print("Carriage Started"); } protected String setPowerUnit() { return "horse" } }
沒有問題!抽象類別可以用於需要相同抽象方法的類別上,減少重複的程式碼。
但與介面作比較,明顯可以看到抽象類別不止可以實現抽象方法,更可以包含商業邏輯與私人屬性。
介面與抽象類別在 OO 中有著重要的作用,可以降低程式的耦合與重複,增加彈性,各位可以多加利用!