メソッドオーバーライドの再確認
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 33/91。
「継承」の章で、メソッドのオーバーライドについてすでに学びました。次に、オブジェクト指向プログラミングにおいて最も強力な概念の1つであるポリモーフィズムと、それがどのように結びついているかを探ってみましょう。
ポリモーフィズム(多態性)とは「多くの形態」を意味します。子クラスでメソッドをオーバーライドすると、同じ名前を維持しながら、そのメソッドに異なる形態を与えることになります。親の型を介してオブジェクトを操作するときに、その真価が発揮されます:
<?php
class Animal {
public function speak() {
return "Some sound";
}
}
class Dog extends Animal {
public function speak() {
return "Woof!";
}
}
class Cat extends Animal {
public function speak() {
return "Meow!";
}
}
function makeAnimalSpeak(Animal $animal) {
return $animal->speak();
}
echo makeAnimalSpeak(new Dog()) . "\n";
echo makeAnimalSpeak(new Cat());
出力:
Woof!
Meow!関数 makeAnimalSpeak() は、任意の Animal を受け入れます。それが Dog か Cat のどちらを受け取ったかを認識したり気にしたりすることはありません。PHPは実行時に、実際のオブジェクト型に基づいて、正しいオーバーライドされたメソッドを自動的に呼び出します。
これがポリモーフィズムの実際の動作です。
このアプローチにより、特定の型を知らなくても、関連するオブジェクトのファミリーで動作する柔軟なコードを記述できます。後で新しい動物クラスを追加しても、関数はそれらに対して自動的に動作します。
重要なポイント: メソッドのオーバーライドは、実行時に実際のオブジェクト型によって決定される、同じメソッド呼び出しに対して異なるクラスが異なる応答をすることを可能にすることで、ポリモーフィズムを実現します。
チャレンジ
簡単メソッドのオーバーライドを通じてポリモーフィズムを実証する楽器システムを構築しましょう。ベースとなる Instrument クラスと、それぞれ独自の音を出す2つの子クラスを作成し、単一の関数を使用して任意の楽器をポリモーフィックに演奏します。
コードは4つのファイルに分けて構成します:
Instrument.php— コンストラクタを通じて設定される保護された$nameプロパティを持つInstrumentクラスを作成します。"[name] makes a sound"を返すplay()メソッドを追加します。これが、子クラスがオーバーライドするベースの動作となります。Guitar.php—Instrumentを継承するGuitarクラスを作成します。親ファイルをインクルードしてください。コンストラクタは名前を受け取り、それを親のコンストラクタに渡します。play()メソッドをオーバーライドして、"[name] strums a chord"を返すようにします。Drum.php—Instrumentを継承するDrumクラスを作成します。親ファイルをインクルードしてください。コンストラクタは名前を受け取り、それを親のコンストラクタに渡します。play()メソッドをオーバーライドして、"[name] beats a rhythm"を返すようにします。main.php— GuitarとDrumの両方のファイルをインクルードします。Instrumentパラメータ(型ヒント付き)を受け取り、そのplay()を呼び出した結果を返すperformWithという関数を作成します。この関数はポリモーフィズムを実証します。親クラスの型ヒントを通じて、あらゆる楽器タイプで動作します。
2つの入力を受け取ります:ギターの名前とドラムの名前です。これらの名前で Guitar と Drum を作成します。それぞれを performWith() 関数に渡し、結果をプリントしてください。ギターを先に、次にドラムを、それぞれ改行して出力します。
performWith() が任意の Instrument を受け入れるにもかかわらず、PHPが実行時に実際のオブジェクト型に基づいて、正しいオーバーライドされた play() メソッドを自動的に呼び出すことに注目してください。これがポリモーフィズムの仕組みです!
チートシート
ポリモーフィズムは「多態性(多くの形態)」を意味し、異なるクラスのオブジェクトをその親の型を通じて扱いながら、それぞれの固有の振る舞いを維持することを可能にします。
子クラスでメソッドをオーバーライドすると、PHPは実行時に実際のオブジェクトの型に基づいて、自動的に正しいバージョンのメソッドを呼び出します:
<?php
class Animal {
public function speak() {
return "Some sound";
}
}
class Dog extends Animal {
public function speak() {
return "Woof!";
}
}
class Cat extends Animal {
public function speak() {
return "Meow!";
}
}
function makeAnimalSpeak(Animal $animal) {
return $animal->speak();
}
echo makeAnimalSpeak(new Dog()); // Woof!
echo makeAnimalSpeak(new Cat()); // Meow!
関数 makeAnimalSpeak() は、パラメータの型ヒントを通じて任意の Animal 型を受け入れます。特定のクラスを知る必要はありません。PHPは実行時に実際のオブジェクトの型に基づいて、どのオーバーライドされたメソッドを呼び出すかを決定します。
これにより、特定の型を知らなくても、関連するオブジェクトのファミリーを扱う柔軟なコードが可能になります。新しい子クラスを後から追加しても、既存の関数で自動的に動作します。
自分で試してみよう
<?php
// 楽器のファイルをインクルードします
require_once 'Guitar.php';
require_once 'Drum.php';
// 入力を読み取ります
$guitarName = trim(fgets(STDIN));
$drumName = trim(fgets(STDIN));
// TODO: 以下の機能を持つ performWith 関数を作成してください:
// - Instrument パラメータを受け取る (タイプヒントを使用: Instrument $instrument)
// - 楽器の play() を呼び出した結果を返す
// TODO: $guitarName で Guitar を、$drumName で Drum を作成します
// TODO: それぞれを performWith() に渡し、結果を出力します (ギターが先、次にドラム)
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。