定義一個超類(抽象父類)Shape,提供獲取圖形名稱的通用方法,並宣告抽象方法 getArea() 計算面積。派生 Circle(圓)、Rectangle(矩形)等子類,透過建構子接收參數(半徑、長寬),覆寫 getArea() 實現具體演算法。
// 抽象父類
public abstract class Shape {
// 通用方法:取得類別簡單名稱(Circle、Rectangle 等)
public String getName() {
return this.getClass().getSimpleName();
}
// 抽象方法:強制子類實現具體面積計算
public abstract double getArea();
}
// 圓形
public class Circle extends Shape {
private final double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * Math.pow(radius, 2); // πr²
}
}
// 矩形
public class Rectangle extends Shape {
private final double length;
private final double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double getArea() {
return length * width; // 長 × 寬
}
}
// 測試類
public class Test {
public static void main(String[] args) {
Shape circle = new Circle(1);
System.out.println("圖形的名稱是:" + circle.getName());
System.out.println("圖形的面積是:" + circle.getArea());
Shape rectangle = new Rectangle(1, 1);
System.out.println("圖形的名稱是:" + rectangle.getName());
System.out.println("圖形的面積是:" + rectangle.getArea());
}
}
圖形的名稱是:Circle
圖形的面積是:3.141592653589793
圖形的名稱是:Rectangle
圖形的面積是:1.0

| 概念 | 程式碼體現 | 意義 |
|---|---|---|
| 抽象類 | abstract class Shape | 不可實例化,定義共同協議(介面)與共享實作(getName) |
| 抽象方法 | abstract double getArea() | 無方法體,強制子類提供具體實現,實現「介面契約」 |
| 繼承 | extends Shape | 子類自動擁有 getName(),專注實現 getArea() |
| 多態 | Shape circle = new Circle(1) | 父類引用指向子類物件,編譯期綁定父類型,執行期動態分派 |
| 封裝 | private final double radius | 資料隱藏,建構子初始化,不可變物件模式 |
| 反射獲取名稱 | getClass().getSimpleName() | 避免硬編碼字串,自動同步類別名稱變更 |
public class Triangle extends Shape {
private final double base;
private final double height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double getArea() {
return 0.5 * base * height;
}
}
// 使用:完全不動原有程式碼
Shape triangle = new Triangle(3, 4);
System.out.println(triangle.getName() + " 面積:" + triangle.getArea()); // Triangle 面積:6.0
這正是開放封閉原則 (OCP):對擴充開放、對修改關閉。新增圖形零修改既有類別。
List<Shape> shapes = Arrays.asList(
new Circle(2),
new Rectangle(3, 4),
new Triangle(5, 6)
);
// 總面積
double total = shapes.stream().mapToDouble(Shape::getArea).sum();
// 最大面積圖形
Shape max = shapes.stream().max(Comparator.comparingDouble(Shape::getArea)).orElse(null);
// 分組統計
Map<String, Long> countByType = shapes.stream()
.collect(Collectors.groupingBy(Shape::getName, Collectors.counting()));
Shape 不宣告 abstract 卻有無實作方法,編譯錯誤。getArea() 的子類會繼承抽象方法,導致該子類也變成抽象類,無法實例化。super(...)。com.example.Circle),顯示不友善,應用 getSimpleName()。本範例以抽象類 + 多態優雅解決「同一操作(面積)、不同演算法」的經典問題。掌握此模式,可應用於「薪資計算(全職/兼職/時薪)」、「稅率計算(不同稅制)」、「渲染圖形(SVG/Canvas/WebGL)」等所有策略模式適用場景。