Java 逆引き集 | 継承とポリモーフィズム — 拡張性のある設計

Java Java
スポンサーリンク

継承とポリモーフィズム — 拡張性のある設計

Javaのオブジェクト指向の柱が 継承ポリモーフィズム(多態性)
「共通部分を親にまとめる」「違いは子で表現する」ことで、拡張性と保守性が高まります。初心者向けに、コード例とテンプレートを交えて解説します。


継承(Inheritance)

基本構文

class Parent {
    void greet() { System.out.println("Hello"); }
}

class Child extends Parent {
    void play() { System.out.println("Playing"); }
}
Java
  • extends: 親クラスを継承。親のフィールドやメソッドを利用できる。
  • 再利用: 共通処理を親にまとめることで重複を減らす。
  • 拡張: 子クラスで新しいメソッドを追加できる。

ポリモーフィズム(Polymorphism)

基本の考え方

  • 同じメソッド呼び出しでも、実際の型によって振る舞いが変わる。
  • 親型の変数に子型のインスタンスを代入できる。
class Animal {
    void speak() { System.out.println("???"); }
}

class Dog extends Animal {
    @Override
    void speak() { System.out.println("ワン"); }
}

class Cat extends Animal {
    @Override
    void speak() { System.out.println("ニャー"); }
}

Animal a1 = new Dog();
Animal a2 = new Cat();

a1.speak(); // ワン
a2.speak(); // ニャー
Java

👉 同じ speak() 呼び出しでも、実際のインスタンスに応じて結果が変わる。


設計のメリット

  • 拡張性: 新しい子クラスを追加するだけで既存コードに組み込める。
  • 保守性: 共通処理は親に集約、差分だけ子で表現。
  • 柔軟性: 呼び出し側は「親型」で扱うため、具体的な型に依存しない。

例題で練習

例題1: 図形の面積計算

abstract class Shape {
    abstract double area(); // 共通インターフェース
}

class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }
    @Override
    double area() { return Math.PI * r * r; }
}

class Rectangle extends Shape {
    double w, h;
    Rectangle(double w, double h) { this.w = w; this.h = h; }
    @Override
    double area() { return w * h; }
}

// 呼び出し側
Shape[] shapes = { new Circle(2), new Rectangle(3, 4) };
for (Shape s : shapes) {
    System.out.println(s.area());
}
Java

👉 新しい図形クラスを追加しても、同じ area() 呼び出しで処理できる。


例題2: 支払い方法の拡張

interface Payment {
    void pay(int amount);
}

class CreditCardPayment implements Payment {
    public void pay(int amount) {
        System.out.println("クレジットカードで " + amount + " 円支払い");
    }
}

class CashPayment implements Payment {
    public void pay(int amount) {
        System.out.println("現金で " + amount + " 円支払い");
    }
}

// 呼び出し側
Payment p = new CreditCardPayment();
p.pay(5000);

p = new CashPayment();
p.pay(2000);
Java

👉 呼び出し側は Payment インターフェースに依存するだけ。新しい支払い方法を追加しても既存コードは変更不要。


例題3: ゲームキャラクターの行動

class Character {
    void attack() { System.out.println("攻撃!"); }
}

class Warrior extends Character {
    @Override
    void attack() { System.out.println("剣で斬る!"); }
}

class Mage extends Character {
    @Override
    void attack() { System.out.println("魔法を唱える!"); }
}

Character[] party = { new Warrior(), new Mage() };
for (Character c : party) {
    c.attack();
}
Java

👉 同じ attack() 呼び出しでも、キャラクターごとに振る舞いが変わる。


テンプレート集

継承

class 子クラス extends 親クラス {
    // 親のメソッドを利用 or オーバーライド
}
Java

ポリモーフィズム

親型 変数 = new 子クラス();
変数.メソッド(); // 実際の子クラスの処理が呼ばれる
Java

抽象クラス

abstract class Base {
    abstract 戻り値型 メソッド名(...);
}
Java

インターフェース

interface インターフェース名 {
    戻り値型 メソッド名(...);
}
Java

まとめ

  • 継承: 共通処理を親にまとめ、子で拡張。
  • ポリモーフィズム: 同じ呼び出しでも型ごとに振る舞いを変えられる。
  • 抽象クラス/インターフェース: 拡張性のある設計の基本。

👉 練習課題として「乗り物クラス」を作り、CarBike を継承させて move() をオーバーライドすると、ポリモーフィズムの効果を体感できます。

タイトルとURLをコピーしました