この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: オブジェクト指向の概念
SEOタイトル: オブジェクト指向プログラミング (OOP) 完全ガイド

この記事の要点
  • OOP の三大原則: カプセル化 / 継承 / ポリモーフィズム(+ 抽象化を加え四大原則とも)
  • クラス = 設計図、オブジェクト = 設計図から作った実体 (インスタンス)
  • SOLID 原則: 単一責任 / 開放閉鎖 / Liskov / インタフェース分離 / 依存性逆転
  • デザインパターン: Singleton / Factory / Observer / Strategy / Decorator など 23 種類が GoF で有名
  • 関数型 (FP) との対比: OOP は状態 + 振る舞いをカプセル化、FP は純粋関数 + 不変データ

OOP とは何か

オブジェクト指向プログラミング (Object-Oriented Programming, OOP) は、データ(状態)と振る舞い(メソッド)をオブジェクトという単位でまとめて扱うパラダイムです。1960 年代の Simula、1970 年代の Smalltalk が祖。現代では Java / C++ / C# / Python / Ruby / PHP / Kotlin / Swift など多くの言語が採用。

三大原則 (+ 抽象化で四大原則)

原則意味キーワード
カプセル化 (Encapsulation)データを隠蔽し、操作はメソッド経由private, getter/setter
継承 (Inheritance)親の機能を子に引き継ぐextends, super
ポリモーフィズム (Polymorphism)同じインタフェースで異なる振る舞いoverride, interface
抽象化 (Abstraction)本質的な特徴だけを抽出abstract, interface

クラスとオブジェクト

// クラス = 設計図
public class Car {
    // フィールド(属性 / 状態)
    private String color;
    private int speed;

    // コンストラクタ
    public Car(String color) {
        this.color = color;
        this.speed = 0;
    }

    // メソッド(振る舞い)
    public void accelerate(int delta) {
        this.speed += delta;
    }

    public int getSpeed() {
        return speed;
    }
}

// オブジェクト = 設計図から作った実体
Car redCar  = new Car("red");    // インスタンス化
Car blueCar = new Car("blue");

redCar.accelerate(50);
System.out.println(redCar.getSpeed());  // 50
System.out.println(blueCar.getSpeed()); // 0  ← 別個の状態

カプセル化の実例

public class BankAccount {
    private long balance;    // ★ private で外部から直接触れない

    public BankAccount(long initial) {
        if (initial < 0) throw new IllegalArgumentException();
        this.balance = initial;
    }

    public void deposit(long amount) {
        if (amount <= 0) throw new IllegalArgumentException();
        balance += amount;
    }

    public void withdraw(long amount) {
        if (amount > balance) throw new IllegalStateException("残高不足");
        balance -= amount;
    }

    public long getBalance() { return balance; }
}

// ❌ 直接書換できない(コンパイルエラー)
// account.balance = -1000000;

// ✅ メソッド経由で必ずバリデーション通る
account.withdraw(500);

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

// 共通の interface
interface Shape {
    double area();
}

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

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

// 利用側は Shape インタフェースだけ知っていればよい
Shape[] shapes = { new Circle(3), new Rectangle(2, 4) };
for (Shape s : shapes) {
    System.out.println(s.area());    // 実体に応じた計算
}

SOLID 原則

原則名前要点
SSingle Responsibilityクラスの責務は 1 つ。変更理由が 1 つに
OOpen/Closed拡張に開き、変更に閉じる
LLiskov Substitution子は親と置換可能
IInterface Segregation1 つの大インタフェースより小さな複数
DDependency Inversion具象でなく抽象に依存

主要デザインパターン (GoF 23 種から抜粋)

パターン分類用途
Singleton生成クラスのインスタンスをただ 1 つに(DBconnection 等)
Factory Method生成生成処理を子クラスに委譲
Abstract Factory生成関連オブジェクト群をまとめて生成
Builder生成複雑なオブジェクトを段階的に構築
Observer振る舞い状態変化を購読者に通知(イベント駆動)
Strategy振る舞いアルゴリズムを差し替え可能に
Decorator構造既存オブジェクトに動的に機能追加
Adapter構造異なる API を適合させる
Facade構造複雑なサブシステムへの簡略 API

Singleton の実装例

public class DbConnection {
    private static DbConnection instance;
    private DbConnection() { /* 接続初期化 */ }

    public static synchronized DbConnection getInstance() {
        if (instance == null) {
            instance = new DbConnection();
        }
        return instance;
    }
}

// 利用
DbConnection conn = DbConnection.getInstance();

Strategy の例

from abc import ABC, abstractmethod

class SortStrategy(ABC):
    @abstractmethod
    def sort(self, data): ...

class QuickSort(SortStrategy):
    def sort(self, data):
        # ... quicksort 実装
        return sorted(data)

class MergeSort(SortStrategy):
    def sort(self, data):
        # ... mergesort 実装
        return sorted(data)

class Sorter:
    def __init__(self, strategy: SortStrategy):
        self.strategy = strategy

    def execute(self, data):
        return self.strategy.sort(data)

# アルゴリズムを実行時に差し替え
sorter = Sorter(QuickSort())
print(sorter.execute([3,1,2]))

言語別の OOP 機能比較

機能JavaPythonC#PHP
クラス定義classclassclassclass
継承extends(Parent):extends
多重継承××× (trait あり)
interfaceABC で代替
抽象クラスabstractABCabstractabstract
final×sealedfinal
genericstyping.Generic(8.0+ 弱)

OOP と関数型 (FP) の対比

観点OOPFP
中心概念オブジェクト(状態+振る舞い)純粋関数 + 不変データ
状態カプセル化された可変状態イミュータブル
制御メッセージパッシング / 命令型関数合成 / 宣言的
再利用継承 / Composition高階関数 / カリー化
並行性ロックが必要不変なので安全
代表言語Java, C#, C++Haskell, Erlang, F#
マルチパラダイムScala / Kotlin / Python / JS は両方サポート

現代の OOP 設計指針

  • Composition Over Inheritance: 継承より委譲を優先
  • Tell Don't Ask: 状態を尋ねるな、命じよ(カプセル化徹底)
  • Law of Demeter: a.b.c.d のような連鎖アクセスを避ける
  • イミュータブルファースト: 状態を持たせない設計を優先(Java の record / Kotlin の data class)
  • ドメイン駆動設計 (DDD): ビジネス概念をクラスに直接マップ
  • クリーンアーキテクチャ: 依存方向を内側(ドメイン)に向ける

FAQ

Q: 「オブジェクト指向は終わった」と聞きました
A: 一部の極端な意見。実際はOOP + FP のハイブリッドが主流。Java / Kotlin / Scala に Stream / map / filter のような FP 要素が入り、Haskell には型クラスがある。両者の長所を組み合わせて使うのが現代です。

Q: クラスを使わない OOP は?
A: JavaScript の prototype ベース、Go の構造体 + メソッド + interface など。クラスは OOP の一実装に過ぎません。

Q: SOLID は今でも有効?
A: 概念は今も有効ですが、マイクロサービスや関数型では別の指針(純粋性、単方向データフロー)も重要。原理主義は避けてバランスを。