継承
https://www.php.net/manual/ja/language.oop5.inheritance.php
子クラス(サブクラス)は、親クラスから public
と protected
の、メソッドや、プロパティや定数をすべて引き継ぎます。
そのため、子クラスで定義が無くても親クラスにあれば、使う事ができます。
また、子クラスは、親クラスのメソッドを上書きする事ができます。
上書きするメソッドは「シグネチャに互換性がある」必要があります。このルールはコンストラクタのみ例外となります。
親クラスと子クラスの上書きするメソッドが「同じアクセス権、同じ数、同じ型の引数と戻り値」であれば「シグネチャに互換性がある」となります。
メソッドやプロパティ、そして定数の アクセス権 に関するルールは、子クラスで緩めることが可能です(厳しくすることはできません)。
アクセス権を緩めても「シグネチャに互換性がある」となります。
また、引数や戻り値の型は、一定のルールに従って「狭くしたり」「広くしたり」する事ができ、そのルールに従っている限り「シグネチャに互換性がある」となります。
この「型のルール」については、下の「共変性と反変性」で解説をします。
共変性と反変性
https://www.php.net/manual/ja/language.oop5.variance.php
型の「より狭い」「より広い」について、まずは理解をしておきましょう。
例えば string|int|float
が int|float
になった場合、これは「型の範囲が狭くなった」と言います。
他にも「クラスの型が、子クラスの型に変更されている場合」などが「型の範囲が狭くなった」一例です。
従って、その逆が「型の範囲が広くなった」と言われます。
共変性とは、子クラスのメソッドの戻り値の型が、親クラスの戻り値の型よりも”狭い型”を返すことを許すことです。
一方で、反変性とは、子クラスのメソッドの引数の型が、親クラスのメソッドの引数の型よりも”広い型”を指定することを許すものです。
finalキーワード
https://www.php.net/manual/ja/language.oop5.final.php
キーワード final を前に付けて定義されたメソッドや定数は、子クラスから上書きできません。
クラス自体がfinalと定義された場合には、このクラスを継承することはできません。
readonlyの継承(PHP8.1.0以降)
https://www.php.net/manual/ja/language.oop5.inheritance.php
読み取りと書き込みが両方可能なプロパティを、 readonly
として上書きしてはいけません。
逆も同じです。
内部クラスと戻り値の型の互換性(PHP8.1.0以降)
https://www.php.net/manual/ja/language.oop5.inheritance.php
戻り値の型が不一致な場合、警告が発生します。これは「明示的に戻り値の型を宣言していないメソッドを継承した時」にも発生します。
(もしPHP のバージョン間の互換性を保ちたい等の理由で)戻り値の型を宣言できない場合、アトリビュート ReturnTypeWillChange
を追加することで警告を抑止できます。
このコラムに関連するコードはこちらになります
https://github.com/php-engineer-examination/php8_column_expert/blob/main/src/025.php
https://github.com/php-engineer-examination/php8_column_expert/blob/main/src/025_NonTested.php