継承とポリモーフィズム — 拡張性のある設計
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まとめ
- 継承: 共通処理を親にまとめ、子で拡張。
- ポリモーフィズム: 同じ呼び出しでも型ごとに振る舞いを変えられる。
- 抽象クラス/インターフェース: 拡張性のある設計の基本。
👉 練習課題として「乗り物クラス」を作り、Car と Bike を継承させて move() をオーバーライドすると、ポリモーフィズムの効果を体感できます。

