Java – 物件導向 – 介面

這個單元要介紹的是interface, 介面, 一樣又是個文言文, 先不理會.

觀念建立


在現實生活中, 很多東西都是遵循特定的規格或是概念而來的. 例如說: 車子, 什麼是汽車, 描述一下吧.

  • 油量/耗油/加油
  • 油門功能
  • 煞車功能
  • 方向盤

 

這些都是汽車的功能, 但是如何實現這些功能, 並不是在汽車中去定義, 而是由各個不同種類的汽車去實現. 這就是介面的概念, 寫成程式如下:

Car.java

public interface Car {
  double getOil();
  void addOil(double oil);
  double getSpeed();
  void upSpeed();
  void downSpeed();
  void changeAngle(int angle);
}

 

假設有一種汽車, 叫做 Altia

public class Altia implements Car {
  private final double maxOil = 60;	// 油箱最大50公升
  private final double maxSpeed = 200;	// 最高時速
  private double oil;		// 油量
  private double speed;	// 時速
  private int angle;		// 角度

  @Override
  public double getOil() {
    return oil;
  }

  @Override
  public void addOil(double oil) {
    if (this.oil + oil >= 0 && this.oil + oil <= maxOil) {
      this.oil += oil;
    }
  }

  @Override
  public double getSpeed() {
    return speed;
  }

  @Override
  public void upSpeed() {
    if (speed < 5) {
      speed = 5;
    }else if (speed *1.5 < maxSpeed) {
      speed *= 1.5;
    }
  }

  @Override
  public void downSpeed() {
    speed = speed < 5? 0 : speed*0.5; 
  }

  @Override
  public void changeAngle(int angle) {
    this.angle = angle;
  }

}

 

另一種汽車, 叫做 Bens

public class Bens implements Car {
  private final double maxOil = 80;	// 油箱最大80公升
  private final double maxSpeed = 240;	// 最高時速
  private double oil;		// 油量
  private double speed;	// 時速
  private int angle;		// 角度

  @Override
  public double getOil() {
    return oil;
  }

  @Override
  public void addOil(double oil) {
    if (this.oil + oil >= 0 && this.oil + oil <= maxOil) {
      this.oil += oil;
    }
  }

  @Override
  public double getSpeed() {
    return speed;
  }

  @Override
  public void upSpeed() {
    if (speed < 10) {
      speed = 10;
    }else if (speed *1.7 < maxSpeed) {
      speed *= 1.7;
    }
  }

  @Override
  public void downSpeed() {
    speed = speed < 10? 0 : speed*0.4; 
  }

  @Override
  public void changeAngle(int angle) {
    this.angle = angle;
  }

}

 

當然, 你我都知道的是, 這兩款汽車不只是這樣而已, 還有其他很厲害的功能還沒有寫上去. 但是, 這裡要說的重點是, 這兩個類別所產生出來的物件實體, 一定是汽車. 因為:

  • 在類別的宣告中, 對外宣稱實作出汽車(implements Car)
  • 在類別中定義中, 也實作了汽車該有的功能的細節({……})

 

當需要一台汽車的時候, 這兩個類別的物件實體都吻合汽車所定義的規格, 都是(is-a)汽車的物件實體. 所以當我說, 我想去租車店租一台汽車, 只要是汽車都可以, 而店員交給我的是Altia的汽車, 或是Bens的汽車都吻合我的需求, 我都可以使用, 因為有油門功能, 煞車功能, 知道目前時速等等. 至於該款汽車是否有特殊功能, 我並不需要知道, 也使用不到. 接著就開車上路了, 當踩下油門的時候, 兩台汽車所表現出來的效能, 確實有不同的表現, 因為在上面兩段程式中, 可以清楚看到, 當一開始速度都是0.0, 各自呼叫一次upSpeed()的時候, Altia的物件實體的速度為5, 而Bens的速度為10. 這在現實生活中, 應該算是普遍的認知, 並不會很特殊的觀念. 但是在物件導向中, 這就是由介面(interface)所表現出來的特徵.

以白話文的方式介紹完介面之後, 就開始慢慢導入文言文.

介面格式


介面的定義格式, 與類別大致相同, 只是將 class 改為 interface

public interface Car {
}

所有的interface, 無論是否有註記 public 的存取修飾字, 一率都是以 public 的存取範圍視之. 試想, 規格這種東西, 本來就沒有安全機制可言, 只是定義而已, 沒有任何實作細節, 更何況, 規格訂出來就是要用來實作(implement), 所以, 這個觀念應該很容易理解, 一律 public.

而其內部定義的方法:

  • 無需特別註記, 通通都是 public
  • 只有宣告定義, 而無任何實作, 也不需要加上 abstract(抽象) 的修飾字, 因為通通都是抽象方法.

 

當一個類別要實作介面時:

  • 宣告定義上加上 implements 介面名稱
    • 該介面定義的全部方法必須全部實作({……})
    • 如果沒有全部實作, 則該類別必須宣告為抽象類別, 因為相當於尚有抽象方法尚未實作.
  • 可以同時implements 一個以上的 interface, 中間以逗號分隔即可.

 

實作介面可以同時多個的觀念, 就好像有個人, 既是Java程式設計師, 也是網路工程師一樣, 兩種規格都吻合.

 

繼承關係


不同介面之間也存在繼承關係.

上面提到的汽車, 當想要繼續定義跑車, 而跑車應該是完全具備汽車該有的功能之外, 還要有一些特別的功能, 才能被稱之為跑車.(以上內容純屬想像, 如有偏差, 請包容)

此時, 定義跑車(Sports Car)的介面時, 就不再需要重新將汽車的方法再次重寫一遍, 只需要宣吿定義即可, 而且可以多重繼承.

extends 其他介面, 更多介面, …

SportsCar.java

public interface SportsCar extends Car {
  void toHighSpeed();
  void toNormalSpeed();
}

 

那來設計一款 Porschy 跑車吧.

public class Porschy implements SportsCar {

  @Override
  public double getOil() {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public void addOil(double oil) {
    // TODO Auto-generated method stub
    
  }

  @Override
  public double getSpeed() {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public void upSpeed() {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void downSpeed() {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void changeAngle(int angle) {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void toHighSpeed() {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void toNormalSpeed() {
    // TODO Auto-generated method stub
    
  }

}

此時, 除了SportsCar的介面定義的兩個方法之外, 還必須將Car介面定義的方法也實作出來, 才會是SportsCar的物件實體.

(所以咧, 難怪跑車比較貴吼…)

 

 

 

 

 

本站資源一切隨緣,
不用註冊, 不看廣告
如果對您有所助益,
歡迎功德隨喜, 金額隨意,
請點擊以下...(感謝您)

功德箱/打賞箱

%d bloggers like this: