あっぽログ
← 記事一覧に戻る

PHPのオブジェクト指向入門:クラス・継承・インターフェースを使いこなす

PHPのオブジェクト指向とは

PHPは手続き型の書き方もできますが、オブジェクト指向プログラミング(OOP) を活用することでコードの再利用性や保守性が大幅に向上します。LaravelなどのモダンなPHPフレームワークもOOPを前提に設計されているため、基本を押さえておくことは非常に重要です。

この記事では「クラス」「継承」「インターフェース」「抽象クラス」という4つの柱を順番に解説します。


クラスとインスタンス

PHPでクラスを定義するには class キーワードを使います。クラスはオブジェクトの設計図であり、そこから生成される実体をインスタンスと呼びます。

<?php

class User
{
    // プロパティ
    public string $name;
    public int $age;

    // コンストラクタ
    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age  = $age;
    }

    // メソッド
    public function greet(): string
    {
        return "こんにちは、{$this->name}さん({$this->age}歳)です。";
    }
}

$user = new User('田中', 28);
echo $user->greet();
// こんにちは、田中さん(28歳)です。

アクセス修飾子

プロパティやメソッドには以下の3種類のアクセス修飾子を付けられます。

修飾子説明
publicどこからでもアクセス可能
protectedクラス自身とサブクラスからアクセス可能
privateクラス自身からのみアクセス可能
<?php

class BankAccount
{
    private float $balance;

    public function __construct(float $initialBalance)
    {
        $this->balance = $initialBalance;
    }

    public function deposit(float $amount): void
    {
        $this->balance += $amount;
    }

    public function getBalance(): float
    {
        return $this->balance;
    }
}

$account = new BankAccount(1000.0);
$account->deposit(500.0);
echo $account->getBalance(); // 1500
// $account->balance; // エラー!privateなのでアクセス不可

継承

既存のクラスを親クラスとして、その機能を引き継いだ子クラスを作ることを「継承」と言います。extends キーワードを使います。

<?php

class Animal
{
    public function __construct(protected string $name) {}

    public function speak(): string
    {
        return "{$this->name}が鳴いています。";
    }
}

class Dog extends Animal
{
    // 親のメソッドをオーバーライド
    public function speak(): string
    {
        return "{$this->name}:ワンワン!";
    }

    public function fetch(): string
    {
        return "{$this->name}がボールを取ってきた!";
    }
}

class Cat extends Animal
{
    public function speak(): string
    {
        return "{$this->name}:ニャー!";
    }
}

$dog = new Dog('ポチ');
$cat = new Cat('タマ');

echo $dog->speak();  // ポチ:ワンワン!
echo $dog->fetch();  // ポチがボールを取ってきた!
echo $cat->speak();  // タマ:ニャー!

parentキーワード

子クラスから親クラスのメソッドを呼び出すには parent:: を使います。

<?php

class AdminUser extends User
{
    public function __construct(string $name, int $age, private string $role)
    {
        parent::__construct($name, $age); // 親のコンストラクタを呼び出す
    }

    public function greet(): string
    {
        return parent::greet() . "(役割:{$this->role})";
    }
}

$admin = new AdminUser('佐藤', 35, '管理者');
echo $admin->greet();
// こんにちは、佐藤さん(35歳)です。(役割:管理者)

インターフェース

インターフェースは「このクラスは必ずこのメソッドを持つ」という契約を定義します。interface キーワードで宣言し、implements で実装します。

<?php

interface Notifiable
{
    public function notify(string $message): void;
}

interface Loggable
{
    public function log(string $event): void;
}

// 複数のインターフェースを同時に実装できる
class EmailService implements Notifiable, Loggable
{
    public function notify(string $message): void
    {
        echo "メール送信: {$message}\n";
    }

    public function log(string $event): void
    {
        echo "ログ記録: {$event}\n";
    }
}

$service = new EmailService();
$service->notify('注文が完了しました');
$service->log('order.completed');

インターフェースを型ヒントとして使うことで、どの具体クラスが来ても動く柔軟なコードが書けます。

<?php

function sendAlert(Notifiable $notifier, string $message): void
{
    $notifier->notify($message);
}

// EmailServiceはNotifiableを実装しているので渡せる
sendAlert(new EmailService(), 'サーバーエラーが発生しました');

抽象クラス

抽象クラスはインターフェースと継承の中間的な存在です。共通の実装は持ちつつ、一部のメソッドはサブクラスに実装を強制したい場合に使います。

<?php

abstract class Shape
{
    // 抽象メソッド:サブクラスで必ず実装する
    abstract public function area(): float;

    // 共通の具体的なメソッド
    public function describe(): string
    {
        return get_class($this) . "の面積は " . $this->area() . " です。";
    }
}

class Circle extends Shape
{
    public function __construct(private float $radius) {}

    public function area(): float
    {
        return M_PI * $this->radius ** 2;
    }
}

class Rectangle extends Shape
{
    public function __construct(
        private float $width,
        private float $height
    ) {}

    public function area(): float
    {
        return $this->width * $this->height;
    }
}

$shapes = [new Circle(5.0), new Rectangle(4.0, 6.0)];

foreach ($shapes as $shape) {
    echo $shape->describe() . "\n";
}
// Circleの面積は 78.539816... です。
// Rectangleの面積は 24 です。

まとめ

PHPのオブジェクト指向の主要な概念を整理します。

概念キーワード用途
クラス定義classオブジェクトの設計図を作る
継承extends既存クラスの機能を引き継ぐ
インターフェースinterface / implementsメソッドの契約を定義する
抽象クラスabstract共通実装+強制メソッドを定義する

OOPを使いこなすことで、コードの重複を減らし、変更に強い設計が実現できます。LaravelのEloquentモデルやSymfonyのサービスクラスも、これらの概念の上に成り立っています。まずは小さなクラスを書くところから始めてみましょう!

← 記事一覧に戻る