#01 オブジェクト指向プログラミング入門

クラスとオブジェクト——現実世界をコードで表現する

オブジェクト指向とは何か

プログラミングを学び始めると、最初は「手続き型」のコードを書きます。上から順番に処理を書いていくスタイルです。これでも小さなプログラムなら十分ですが、コードが大きくなると管理が難しくなってきます。

オブジェクト指向プログラミング(OOP)は、現実世界の「モノ」をコードに落とし込む考え方です。人、商品、注文——こうした現実のモノをプログラム上の「オブジェクト」として表現し、それぞれが自分のデータと振る舞いを持ちます。

このシリーズでは、OOPの核となる概念をPHP 8.xのコードを使いながら一つずつ丁寧に解説していきます。


クラスとオブジェクトの関係

まず最も大切な概念を押さえましょう。

  • クラス = 設計図
  • オブジェクト = 設計図から作られた実体(インスタンス)

たとえば「人間」というクラスがあれば、「田中さん」「鈴木さん」はそれぞれ別々のオブジェクトです。同じ設計図(クラス)から作られますが、名前や年齢はそれぞれ異なります。

手続き型との比較

手続き型で「人」を表現しようとするとこうなります。

// NG例:手続き型
$name = '田中太郎';
$age = 30;

function greet(string $name): string {
    return "こんにちは、{$name}です。";
}

echo greet($name);

データと処理がバラバラです。人が増えるほど変数も関数も増えていき、どこに何があるかわからなくなります。


PHPでクラスを定義する

オブジェクト指向では、関連するデータと処理をひとまとめにします。

// OK例:クラスを使う
class Person
{
    public string $name;
    public int $age;

    public function greet(): string
    {
        return "こんにちは、{$this->name}です。";
    }
}

$person = new Person();
$person->name = '田中太郎';
$person->age = 30;

echo $person->greet(); // こんにちは、田中太郎です。

class キーワードでクラスを宣言し、new キーワードでオブジェクト(インスタンス)を作ります。$this はそのオブジェクト自身を指します。


コンストラクタ——オブジェクトを初期化する

上の例では、オブジェクトを作った後に $person->name = ... と別々に値をセットしていました。これは少し不便です。コンストラクタを使えば、オブジェクト生成時に初期値をまとめてセットできます。

class Person
{
    public string $name;
    public int $age;

    // コンストラクタ:new Person() のときに自動で呼ばれる
    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

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

$person = new Person('田中太郎', 30);
echo $person->greet(); // こんにちは、田中太郎です。30歳です。

__construct という特別なメソッドがコンストラクタです。new Person('田中太郎', 30) と書くと自動的に呼ばれます。

PHP 8.0 のコンストラクタプロモーション

PHP 8.0以降では、コンストラクタの引数宣言とプロパティ定義を一度に書ける「コンストラクタプロモーション」が使えます。コードがスッキリします。

class Person
{
    // public をつけるだけでプロパティとして宣言・代入される
    public function __construct(
        public string $name,
        public int $age,
    ) {}

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

$person = new Person('田中太郎', 30);
echo $person->greet();

プロパティとメソッド

クラスの構成要素を整理しましょう。

用語意味
プロパティクラスが持つデータ(変数)$name, $age
メソッドクラスが持つ処理(関数)greet()
インスタンスクラスから生成されたオブジェクトnew Person(...)

メソッドをもう少し充実させてみましょう。

class Person
{
    public function __construct(
        public string $name,
        public int $age,
    ) {}

    public function greet(): string
    {
        return "こんにちは、{$this->name}です。";
    }

    public function isAdult(): bool
    {
        return $this->age >= 18;
    }

    public function haveBirthday(): void
    {
        $this->age++;
    }
}

$person = new Person('山田花子', 17);
echo $person->isAdult() ? '成人' : '未成年'; // 未成年

$person->haveBirthday();
echo $person->isAdult() ? '成人' : '未成年'; // 成人

isAdult() は「成人かどうか」を返すメソッド、haveBirthday() は誕生日を迎えて年齢を増やすメソッドです。オブジェクトが自分自身のデータを操作しています。


複数のオブジェクトを作る

同じクラスから複数のオブジェクトを作れます。それぞれ独立したデータを持ちます。

$alice = new Person('Alice', 25);
$bob   = new Person('Bob', 32);

$alice->haveBirthday();

echo $alice->age; // 26
echo $bob->age;   // 32(Aliceの操作は影響しない)

$alice$bob は別々のオブジェクトなので、一方を変更しても他方には影響しません。


まとめ

この記事では、OOPの基本中の基本を学びました。

  • クラスはデータと処理をまとめた設計図
  • オブジェクトnew で作るクラスの実体
  • コンストラクタ __construct() でオブジェクト生成時の初期化ができる
  • プロパティはオブジェクトのデータ、メソッドはオブジェクトの振る舞い
  • PHP 8.0のコンストラクタプロモーションでコードを簡潔にできる

次回はカプセル化——プロパティを外部から直接操作させない仕組みについて学びます。「なぜプロパティを public にしてはいけないのか」という疑問に答えます。