10_OOP基礎(カプセル化・継承・ポリモーフィズム)

対象:C言語経験者 / 試験問2の3大テーマです。概念と試験でのキーワードを整理します


■ 1. カプセル化

フィールドを private にして外部から直接アクセスできなくし、public なメソッド経由でのみ操作させる仕組みです。

前の単元で「p1.age = 999; とできてしまう」という問題がありました。これをカプセル化で防ぎます。

class Person {
    private String name;   // private:外部から直接アクセス不可
    private int    age;

    Person(String name, int age) {
        this.name = name;
        this.age  = (age >= 0) ? age : 0;  // 不正な値を弾ける
    }

    // getter:値を取り出すメソッド
    public String getName() { return name; }
    public int    getAge()  { return age;  }

    // setter:値を設定するメソッド(検証できる)
    public void setAge(int age) {
        if (age >= 0) this.age = age;  // 負の値は無視
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person("Taro", 20);
        // p.age = -5;          // コンパイルエラー(private)
        p.setAge(21);            // setterを通すのでOK
        System.out.println(p.getName() + " : " + p.getAge());
    }
}
カプセル化の目的は「不正な状態になるのを防ぐ」ことです。
外から直接変えられないようにして、メソッドの中でチェックできるようにします。
Person クラス public メソッド getName() / setAge() private フィールド name, age 外部 OK ✅ ❌ NG
外部は public メソッド経由でのみアクセスできます。private フィールドへの直接アクセスは NG

■ 2. 継承

既存のクラスのフィールドとメソッドを引き継いで、新しいクラスを作る仕組みです。extends キーワードを使います。

// スーパークラス(親)
class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

    void eat() {
        System.out.println(name + " は食べます。");
    }
}

// サブクラス(子):Animal を継承
class Dog extends Animal {

    Dog(String name) {
        super(name);   // 親のコンストラクタを呼ぶ
    }

    void bark() {
        System.out.println(name + " はワンと吠えます。");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog d = new Dog("ポチ");
        d.eat();    // 親から引き継いだメソッド
        d.bark();   // Dog 独自のメソッド
    }
}
用語内容別名
継承元のクラス既存のクラス。フィールドとメソッドを提供しますスーパークラス・親クラス・基底クラス
継承先のクラス新しく作るクラス。既存のクラスを拡張しますサブクラス・子クラス・派生クラス
extends継承を宣言するキーワード
super()親のコンストラクタを呼ぶ
試験問2では「スーパークラス」「サブクラス」という用語で問われます。
「設計図から設計図を作る」と覚えると理解しやすいです。

■ 3. メソッドのオーバーライド

親クラスのメソッドを子クラスで上書きすることです。オーバーロード(引数違いの同名メソッド)とは別の概念なので混同しないようにしましょう。

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("ニャー!");
    }
}
オーバーロードオーバーライド
場所同じクラス内親クラスと子クラス
引数型・数が違う同じ
目的同名で異なる処理を定義親の処理を子で上書き

■ 4. ポリモーフィズム(多態性)

「同じ操作(メソッド呼び出し)をしても、インスタンスの種類によって異なる動作をする」性質です。

Animal a1 = new Dog("ポチ");   // 親型の変数に子インスタンスを入れられる
Animal a2 = new Cat("タマ");

a1.speak();   // → ワン!(Dog の speak が呼ばれる)
a2.speak();   // → ニャー!(Cat の speak が呼ばれる)

// 配列にまとめて処理できる
Animal[] animals = { new Dog("ポチ"), new Cat("タマ"), new Dog("シロ") };
for (Animal a : animals) {
    a.speak();   // それぞれ異なるメソッドが動く
}
ポリモーフィズムの実用的なメリットは「Animal という型で扱えるため、種類が増えても呼び出し側を変更しなくてよい」点です。

実習:継承とオーバーライドを動かす

10_OOP フォルダに OOPMain.java を作って実行しましょう。

class Shape {
    String color;

    Shape(String color) {
        this.color = color;
    }

    double area() {
        return 0;  // サブクラスでオーバーライドする
    }

    void show() {
        System.out.printf("%s の面積: %.2f%n", color, area());
    }
}

class Circle extends Shape {
    double radius;

    Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }

    @Override
    double area() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    double width, height;

    Rectangle(String color, double width, double height) {
        super(color);
        this.width  = width;
        this.height = height;
    }

    @Override
    double area() {
        return width * height;
    }
}

public class OOPMain {
    public static void main(String[] args) {
        Shape[] shapes = {
            new Circle("赤い円", 5.0),
            new Rectangle("青い長方形", 4.0, 6.0),
            new Circle("緑の円", 3.0)
        };

        for (Shape s : shapes) {
            s.show();
        }
    }
}
赤い円 の面積: 78.54 青い長方形 の面積: 24.00 緑の円 の面積: 47.12

試験(問2)との対応

用語意味
カプセル化データを隠蔽してメソッド経由でのみアクセスさせること
継承(インヘリタンス)既存クラスを引き継いで新クラスを作ること
スーパークラス継承元(親)のクラス
サブクラス継承先(子)のクラス
ポリモーフィズム(多態性)同じ操作でもインスタンスの種類によって動作が変わること
メッセージインスタンスへのメソッド呼び出し(a.speak() など)

■ まとめ

概念一言まとめ
カプセル化private でデータを隠して、public メソッドで操作させます
継承extends で親クラスを引き継ぎます
オーバーライド子クラスで親のメソッドを上書きします(@Override を付けます)
ポリモーフィズム親型の変数に子インスタンスを入れて、異なる動作をさせます