假设你有这个:
<?php
interface Type
{}
class SomeType implements Type
{}
class SomeOtherType implements Type
{}
现在,如果您有一个将 Type
接口(interface)作为构造函数依赖项的抽象类,如下所示:
<?php
abstract class TypeUser
{
public function __construct(Type $type)
{}
}
为什么 PHP 允许您像这样在具体类上重载构造函数:
<?php
class SomeTypeUser extends TypeUser
{
public function __construct(SomeType $type)
{}
}
class SomeOtherTypeUser extends TypeUser
{
public function __construct(SomeOtherType $type)
{}
}
但它不允许您对方法执行相同的操作,只能对构造函数执行此操作 — 如果您尝试对非构造函数方法执行此操作,PHP 会抛出一个严格标准
错误吗?
最佳答案
请阅读:Override method parameter with child interface as a new parameter
TL;DR:如果您使用较窄 类型重载方法参数类型,方法签名会更改并与父方法不兼容。您不能用任意子类替换 TypeUser
的实例,因为重载子类的方法签名与父类的方法签名不兼容,因此没有给出调用此类实例的稳定、已知的接口(interface)。
为什么它适用于构造函数?因为要构造一个实例,您(通常)会对其类名进行硬编码:
$user = new SomeTypeUser($parameter);
这里没有歧义构造函数需要什么参数,你确切地知道你正在实例化什么类。
然而,这里不是这样的:
function (TypeUser $user) {
$user->foo($something);
}
那么,$user
是哪个类的实例? SomeTypeUser
? SomeOtherTypeUser
?完全不同的东西? $user->foo()
的签名是foo(SomeType $type)
还是foo(SomeOtherType $type)
?上面的代码会不会在运行时爆炸?谁知道...
关于php - 为什么 PHP 允许您在构造函数上重载类型提示,但不允许在方法上重载类型提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24803939/