メソッドのオーバーライド
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 23/91。
親クラスから継承されたメソッドが、子クラスが必要とするものに完全には適合しないことがあります。メソッドのオーバーライド(Method overriding)を使用すると、子クラスは親クラスに既に存在するメソッドに対して独自の実装を提供できます。
メソッドをオーバーライドするには、親クラスのメソッドと同じ名前のメソッドを子クラスで定義するだけです。
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
return "$this->name makes a sound";
}
}
class Cat extends Animal {
public function speak() {
return "$this->name says meow";
}
}
$cat = new Cat("Whiskers");
echo $cat->speak();
出力:
Whiskers says meowCatクラスは、親のspeak()メソッドを独自のバージョンで完全に置き換えます。catオブジェクトでspeak()を呼び出すと、PHPは子の実装を使用します。
また、parent:: と独自のロジックを組み合わせることで、親の振る舞いを拡張することもできます。
<?php
class Dog extends Animal {
public function speak() {
return parent::speak() . " - woof woof!";
}
}
$dog = new Dog("Rex");
echo $dog->speak();
出力:
Rex makes a sound - woof woof!重要なポイント: メソッドのオーバーライドにより、子クラスは継承された動作をカスタマイズできます。メソッドを完全に置き換えることも、parent:: を使用して元の実装を拡張することもできます。
チャレンジ
簡単子クラスがメソッドのオーバーライドを通じて、親クラスのメソッドを完全に置き換えたり拡張したりする方法を示す通知システムを構築しましょう。
それぞれ独自の動作を持つ、異なる種類の通知を送信するために連携する3つのファイルを作成します。
Notification.php— すべての通知タイプのベースとなるNotificationクラスを定義します。パブリックな$recipientプロパティと、受信者を受け取って設定するコンストラクタを持つ必要があります。"Sending to [recipient]: [message]"を返すsend($message)メソッドを含めてください。UrgentNotification.php—Notificationを継承するUrgentNotificationクラスを定義します。ファイルの先頭で Notification ファイルを読み込んでください。このクラスはsend($message)メソッドを完全にオーバーライドし、"URGENT to [recipient]: [message]!!!"を返すようにします。接頭辞の "URGENT" と末尾の感嘆符に注意してください。これは、親の動作を完全に置き換える例です。LoggedNotification.php—Notificationを継承するLoggedNotificationクラスを定義します。ファイルの先頭で Notification ファイルを読み込んでください。このクラスはsend($message)をオーバーライドしますが、親の実装を活用します。parent::send($message)を呼び出し、その結果に" [logged]"を追加してください。これは、動作を置き換えるのではなく拡張する例です。
main.php では、3つすべての通知クラスファイルを読み込みます。受信者名と送信するメッセージの2つの入力を受け取ります。各通知タイプのインスタンスを1つずつ作成し(すべて同じ受信者を使用)、それぞれでメッセージを指定して send() を呼び出します。各結果を、通常の通知、緊急通知、ログ記録済み通知の順に、それぞれの行に出力してください。
このチャレンジでは、メソッドオーバーライドの2つのアプローチを示しています。UrgentNotification は親のロジックを独自のフォーマットで完全に置き換え、LoggedNotification は parent:: を使用して元の動作を維持しつつ機能を追加しています。
チートシート
メソッドのオーバーライドを使用すると、子クラスは親クラスから継承したメソッドに対して独自の定義を提供できるようになります。
メソッドをオーバーライドするには、親のメソッドと同じ名前のメソッドを子クラスで定義します。
<?php
class Animal {
public function speak() {
return "makes a sound";
}
}
class Cat extends Animal {
public function speak() {
return "says meow";
}
}
子クラスは、親のメソッドの実装を完全に置き換えます。子オブジェクトで呼び出された場合、PHPは子クラスのバージョンを使用します。
親の振る舞いを置き換えるのではなく拡張するには、parent:: を使用して親のメソッドを呼び出し、独自のロジックを追加します。
<?php
class Dog extends Animal {
public function speak() {
return parent::speak() . " - woof woof!";
}
}
これにより、親の元の振る舞いと子クラスからの追加機能が組み合わされます。
自分で試してみよう
<?php
require_once 'Notification.php';
require_once 'UrgentNotification.php';
require_once 'LoggedNotification.php';
// 入力を読み込む
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: 各通知タイプのインスタンスを1つずつ作成する(すべて同じ受信者を使用)
// TODO: 各通知でメッセージを指定して send() を呼び出す
// 次の順序で、各結果をそれぞれの行に出力する:
// 1. 通常の通知
// 2. 緊急の通知
// 3. ログ記録された通知
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。