本文基於經典教學實驗,通過四個遞進式程序項目,系統講解 Java 面向對象核心機制:接口定義與實現、多態賦值與調用、多接口實現、接口繼承體系。附帶完整源碼、運行結果分析與設計模式思考,適合 Java 進階學習者夯實基礎。
模擬主板通過 PCI 接口統一管理網卡、聲卡等設備,展示接口類型參數實現多態的核心模式。
interface PCI {
void start();
void stop();
}
class NetworkCard implements PCI {
public void start() { System.out.println("send..."); }
public void stop() { System.out.println("Network stop."); }
}
class SoundCard implements PCI {
public void start() { System.out.println("Du Du..."); }
public void stop() { System.out.println("Sound stop."); }
}
class MainBoard {
public void userPCICard(PCI p) { // 接口類型參數
p.start();
p.stop();
}
}
public class Example3 {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
mb.userPCICard(new NetworkCard()); // 多態:傳入不同實現
mb.userPCICard(new SoundCard());
}
}
核心洞察: MainBoard 僅依賴抽象 PCI,不依賴具體實現,符合依賴倒置原則。新增設備只需實現接口,無需修改主板代碼。
需求:設計 Complex 類,支援三種構造器、加減運算、字符串輸出、相等比較。
this(0,0),單參調用 this(real,0)hashCode()(本實驗省略)a-bi,正數輸出 a+biclass Complex {
private double real, im;
public Complex(double real, double im) { this.real = real; this.im = im; }
public Complex() { this(0, 0); }
public Complex(double real) { this(real, 0); }
public Complex add(Complex c) {
return new Complex(this.real + c.real, this.im + c.im);
}
public Complex minus(Complex c) {
return new Complex(this.real - c.real, this.im - c.im);
}
@Override public String toString() {
return im < 0 ? real + "" + im + "i" : real + "+" + im + "i";
}
@Override public boolean equals(Object obj) {
if (!(obj instanceof Complex)) return false;
Complex c = (Complex) obj;
return real == c.real && im == c.im;
}
}
定義 Area(面積)與 Volume(體積)兩個接口,球類 Globe 同時實現:
interface Area { double getArea(); }
interface Volume { double getVolume(); }
class Globe implements Area, Volume {
private double r;
public Globe(double r) { this.r = r; }
public double getArea() { return 4 * Math.PI * r * r; }
public double getVolume() { return (4.0/3) * Math.PI * r * r * r; } // 修正:原代碼 0.75 錯誤
}
測試驗證: 輸入半徑 5cm,表面積 314.16cm²,體積 523.60cm³。
建立 PlaneGraphics(平面圖形)與 SolidGraphics(立體圖形)接口體系:
interface PlaneGraphics {
double area(); // 面積/表面積
double perimeter(); // 周長
}
interface SolidGraphics {
double volume(); // 體積
}
class Rectangle implements PlaneGraphics {
private double a, b;
public Rectangle(double a, double b) { this.a = a; this.b = b; }
public double area() { return a * b; }
public double perimeter() { return 2 * (a + b); }
}
class Cuboid extends Rectangle implements SolidGraphics {
private double c;
public Cuboid(double a, double b, double c) { super(a, b); this.c = c; }
@Override public double area() { // 覆寫為表面積
return 2 * (a*b + b*c + a*c);
}
public double volume() { return a * b * c; }
}
設計亮點: Cuboid 繼承 Rectangle 復用邊長屬性,同時實現 SolidGraphics 擴展三維能力。area() 語義從「面積」自然延伸為「表面積」,體現里氏替換原則的邊界探討。
通過父類引用指向不同子類對象,演示運行時多態:
interface Plan {
void eat();
void play();
}
class Saturday implements Plan {
public void eat() { System.out.println(" 吃甜品"); }
public void play() { System.out.println(" 騎自行車"); }
}
class Sunday implements Plan {
public void eat() { System.out.println(" 吃壽司"); }
public void play() { System.out.println(" 爬山"); }
}
public class Example9 {
public static void main(String[] args) {
weekend(new Saturday());
weekend(new Sunday());
}
static void weekend(Plan p) { // 多態參數
System.out.println(p instanceof Saturday ? "星期六:" : "星期天:");
p.eat();
p.play();
}
}
| 概念 | 關鍵點 | 最佳實踐 |
|---|---|---|
| 接口 | 定義契約,支援多實現、多接口實現 | 接口粒度單一,命名以能動詞或 -able 結尾 |
| 多態 | 父類引用指向子類對象,動態綁定 | 面向接口編程,減少 instanceof 判斷 |
| 構造器鏈 | this() 調用同類構造器,避免代碼重複 | 最完整構造器為主,其他委託調用 |
| equals 重寫 | 自反性、對稱性、傳遞性、一致性、非空性 | 必須重寫 hashCode(),使用 Objects.equals() |
| 接口繼承 | 接口可繼承多接口,類實現多接口 | 組合優於繼承,接口隔離原則 |
Cuboid 繼承 Rectangle 是否違反「正方形不是長方形」的里氏替換原則?如何重構?instanceof 與雙分派模式在多態場景的優劣。