タイトル変更しました
ご指摘いただき、勘違いが分かりましたので、タイトルを以下の通り変更させてもらいました。
PHPでも他のオブジェクト指向で言うオーバーロードができる!!(ただしコンストラクに限る)
↓
PHPでもコンストラクタに限り、シグニチャーの違うオーバーライドができる!!
概要
表題の通りですが、PHPでもコンストラクタに限り引数のシグニチャが異なるオーバーライド(他のオブジェクト指向で言うオーバーロード)ができるというのをマニュアルで確認したというだけのお話です。
PHPではオーバーロードができないという記事をよく見かけるのですが、コンストラクタだけは例外ということが明記されている記事を見かけなかったので(マニュアルにあるから当たり前!?)、残しておこうかと。
[2020-10-06追記]
ご指摘によりオーバーロードはできないことが分かりましたので、以下の記事は、「PHPでもコンストラクタに限り、シグニチャーの違うオーバーライドができる!!」という内容になります。
@error_401 さんありがとうございます!
Manual
サンプルコード
class Base
{
protected $a;
public function __construct(int $a)
{
$this->a = $a;
}
public function test(string $a)
{
echo sprintf('class Base(%s)', $a) . PHP_EOL;
}
}
class A extends Base
{
protected $a;
protected $b;
public function __construct(string $a, int $b)
{
$this->a = $a;
$this->b = $b;
parent::__construct($b);
}
public function test(int $a)
{
echo sprintf('class A(%d)', $a) . PHP_EOL;
}
}
$base = new Base(10);
$base->test(10);
$base->test('xxx');
$a = new A('aaa', 10);
$a->test(10);
//$a->test('xxx');
このコードを実行すると、以下のE_WARNINGレベルのエラーが発生しますが、コンストクタについては何もエラーが発生していないことから、コンストラクタのオーバーライドは例外で、正常にオーバーライド~~(オーバーロード)~~可能なことが分かります。
Warning: Declaration of A::test(int $a) should be compatible with Base::test(string $a) in /var/www/wonder/test_overload.php on line 32
更なる疑問
ここで気になるのが、コンストラクタ以外のメソッドもWARNINGなので、実行自体は止まらず、オーバーライドできているような挙動となることです。
//$a->test('xxx');
のコメントアウトを外すと、以下のエラーが発生することからもオーバーライドして、引数の型が変更できているように見えます。
Fatal error: Uncaught TypeError: Argument 1 passed to A::test() must be of the type int, string given, called in /var/www/wonder/test_overload.php on line 41 and defined in /var/www/wonder/test_overload.php on line 28
まとめ
以上、新たな疑問は発生しましたが、マニュアル及びE_WARNINGレベルのエラーの発生より、
- PHPでは引数のシグニチャーが異なるオーバーライド~~(オーバーロード)~~は基本的に不可
- ただしコンストラクタのみオーバーライド~~(オーバーロード)~~可能
ということが分かりました。