PHPにおける継承・委譲
PHPはもちろん 継承 と 委譲 もできるそうなのでそれらの基礎をまとめました。
そして、それらをいつ使うべきなのか、僕の考えも最後に言及します。
継承
PHPではextends
を使って継承を表現するみたいです。
なお、多重継承はできません。
以下の例では、DogはAnimalを継承し、speakをオーバーライドしていますね。
class Animal {
public function speak() {
echo "Some sound";
}
}
class Dog extends Animal {
public function speak() {
echo "Bark";
}
}
$dog = new Dog();
$dog->speak(); // "Bark"
親クラスのメソッドを呼び出す時は以下のように書けます。
class Dog extends Animal {
public function speak() {
parent::speak();
echo "Bark";
}
}
$dog = new Dog();
$dog->speak(); // "Some soundBark"
委譲
委譲はシンプルですね。渡すだけです。
UserService
はログ出力を Logger
に 委譲 しています。
まぁ、自分でLoggerを作ることはない気はするのですが、例えなので許してください。
class Logger {
public function log(string $message): void {
echo $message;
}
}
class UserService {
private Logger $logger;
public function __construct(Logger $logger) {
$this->logger = $logger;
}
public function createUser(string $name): void {
// 省略
$this->logger->log("Created user: $name");
}
}
interfaceと組み合わせるとUserServiceがあくまでLoggerInterfaceという抽象を使用しているだけなので、より疎結合ですね。
interface LoggerInterface {
public function log(string $message): void;
}
class FileLogger implements LoggerInterface {
public function log(string $message): void {
// ファイルへ書き込み
}
}
class UserService {
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function createUser(string $name): void {
$this->logger->log("Created user: $name");
}
}
どちらを使うべきか?(意見)
アプリケーション固有の知識を含む場合は 委譲
ビジネスロジックなどアプリ固有の処理は、委譲 を選ぶのが無難だと思います。
ビジネスロジックというよく変更が加えられるものを最初から正しく継承の階層で表現するのは非常に難しいと考えています。
なので、基本的には継承はあまり使わない方針で良いのかなと。
技術的・共通機能の再利用には 継承 を使えるかも?
ビジネスロジックに依存しない、技術のみで完結する要素は継承を使ってもまぁ良いですが、これも使わないほうが無難ではあるかなと。
ファイルローダー等はフレームワークが用意してくれていますし。
ただ、フレームワークで提供されているようなクラスは継承しても良いと考えています。
フレームワーク自体、技術的・共通機能ですから。
最後に
常に迷ったら「継承より委譲」と考えています。
これはPHPに限った話ではないですが。
また一つ学びが増えました。