😀

PHPのオブジェクト指向について復習してみた

に公開1

普段、ReactやNext.js、Node.jsを使って開発していて、オブジェクト指向を使う機会が少ないです。
忘備録を兼ねて、復習したことをまとめます。

PHPのオブジェクト指向で絶対に知っておくべきこと


クラスとオブジェクト

クラスはオブジェクトの設計図であり、オブジェクトはクラスの実体です。再利用可能なコードを書いたり、実世界の概念を表現したりする際に使用します。

class User {
  public $name;

  public function greet() {
    return "Hello, " . $this->name;
  }
}

$user = new User();
$user->name = "Taro";
echo $user->greet(); // Hello, Taro

コンストラクタ

オブジェクト作成時に初期化処理を行う特殊なメソッドです。オブジェクト生成と同時に初期設定を行いたい場合に使用します。

class User {
  private $name;

  public function __construct($name) {
    $this->name = $name;
  }

  public function greet() {
    return "Hello, " . $this->name;
  }
}

$user = new User("Taro");
echo $user->greet(); // Hello, Taro

静的プロパティと静的メソッド(static)

インスタンスを生成せずにクラス名から直接アクセスできるプロパティやメソッドです。共通の設定やカウンターなどに便利です。

class Counter {
  public static $count = 0;

  public static function increment() {
    self::$count++;
  }
}

Counter::increment();
echo Counter::$count; // 1


継承

既存のクラスを拡張して新しいクラスを作成する仕組みです。共通の処理をまとめたり、拡張性を高めたりするために利用します。

class Animal {
  public function speak() {
    return "Animal speaks";
  }
}

class Dog extends Animal {
  public function speak() {
    return "Woof!";
  }
}

$dog = new Dog();
echo $dog->speak(); // Woof!

アクセス修飾子

プロパティやメソッドのアクセス制限を設定します。

  • public: 外部から自由にアクセス可能
  • private: クラス内のみアクセス可能
  • protected: クラス自身と子クラスからアクセス可能

具体例:

class User {
  public $name;
  private $age;
  protected $role;

  public function __construct($name, $age, $role) {
    $this->name = $name;
    $this->age = $age;
    $this->role = $role;
  }

  public function getAge() {
    return $this->age;
  }
}

class Admin extends User {
  public function getRole() {
    return $this->role;
  }
}

$user = new User("Taro", 20, "member");
echo $user->name;      // Taro
// echo $user->age;   // エラー(private)
echo $user->getAge();  // 20

$admin = new Admin("Hanako", 25, "admin");
echo $admin->getRole(); // admin

よくある疑問:

privateにgetterがあるなら、なぜprivateにするの?

private にすることでプロパティを直接外部から変更することを防ぎます。getterを介してアクセスすることで、取得時の条件チェックや整形、変更時の処理を統一的に管理できるため、安全性や保守性が高まります。


GetterとSetter

privateプロパティへの安全なアクセスや更新を提供するメソッドです。

class User {
  private $age;

  public function setAge($age) {
    if ($age > 0) {
      $this->age = $age;
    }
  }

  public function getAge() {
    return $this->age;
  }
}

$user = new User();
$user->setAge(25);
echo $user->getAge(); // 25


インターフェース

クラスが実装するべきメソッドを定義する設計書のようなものです。複数のクラスで統一的にメソッドを扱うために使います。

具体例:

interface Animal {
  public function speak();
  public function move();
}

class Dog implements Animal {
  public function speak() {
    return "Woof!";
  }

  public function move() {
    return "Dog runs";
  }
}

class Bird implements Animal {
  public function speak() {
    return "Tweet!";
  }

  public function move() {
    return "Bird flies";
  }
}

抽象クラス

一部のメソッド実装を子クラスに任せるためのクラスです。共通処理を抽象クラスで定義し、具体的処理を子クラスに任せます。

具体例:

abstract class Animal {
  abstract public function speak();

  public function sleep() {
    return "Sleeping";
  }
}

class Dog extends Animal {
  public function speak() {
    return "Woof!";
  }
}

よくある疑問:

abstractメソッドとpublicメソッドは何が違う?

  • abstract メソッドは処理の内容を定義せず、必ず子クラスで具体的に実装する必要があります。
  • 通常のpublicメソッドは処理内容をそのまま記述でき、子クラスで再定義(オーバーライド)は任意です。

つまり、抽象メソッドを使うことで、特定の処理が子クラスごとに必ず実装されることを保証できるのです。


トレイト(Trait)

複数のクラス間でメソッドを共有するための仕組みです。継承を使わずにコードを再利用する際に便利です。

trait Logger {
  public function log($message) {
    echo $message;
  }
}

class User {
  use Logger;

  public function create() {
    $this->log("User created!");
  }
}

Discussion

naoyuki42naoyuki42

非常に端的にまとめられて復習になりました!
継承か抽象クラスでfinal修飾子についても触れていただきたいなと思いました!