gpt4 book ai didi

php - 如何在 PHP 中的子类继承方法中定义更严格的类型?

转载 作者:行者123 更新时间:2023-12-04 01:18:42 24 4
gpt4 key购买 nike

假设我有三个这样的类(class)。

abstract class A {
abstract protected function doSomething($object): array;
}

class B extends A {
protected function doSomething(SomeObject $object): array
{
// something
}
}

class C extends A {
protected function doSomething(OtherObject $object): array
{
// something
}
}
根据 PHP 的继承原理,上述结构不是合法的 PHP 代码,因为方法定义与基类不兼容。我当然可以做类似的事情
class B extends A {
protected function doSomething($object): array
{
if (!is_a($object, 'SomeObject')) {
throw new Exception('Object passed to method is not of the correct class for this method.');
}

// something
}
}
但我想知道是否有另一种解决方案来实现抽象类中的方法,可以重新定义以仅接受其中特定类型的对象。

最佳答案

您不能不以与您的示例类似的方式自己实现它。
PHP 对协变和逆变的支持 is clearly defined :

Covariance allows a child's method to return a more specific type than the return type of its parent's method. Whereas, contravariance allows a parameter type to be less specific in a child method, than that of its parent.


如果子类能够具有比其父类或接口(interface)更严格的参数要求,这将导致期望值破灭。
例如:假设您有以下内容:
abstract class AbstractParam{}

class ParamOne extends AbstractParam{}
class ParamTwo extends AbstractParam{}
class ParamThree extends AbstractParam{}

abstract class AbstractService {

abstract public function foo(AbstractParam $bar);
}
任何时候你需要使用这个服务的实现,你都会保证传递任何有效的 AbstractParam 实例。至 foo()将是合法的。方法签名清楚地传达了这一点。
如果我可以在继承/实现上更改它,突然间我可以更改 foo()签名至:
public function foo(ParamOne $bar)
契约(Contract)会被打破,你不能依赖 AbstractService安全,因为不再可能通过任何 AbstractParam实例到 foo() ,因此 violating the LSP在此过程中:您不能再用属于该基对象的子类型的对象替换基类的对象,同时保持正确性。
您问题中的方法可行,但由于上述原因,我认为这不是一个很好的设计。如果你真的必须这样做,只需从方法定义中删除类型提示:
abstract class AbstractService {

abstract public function foo($bar);
}

class ConcreteService extends AbstractService {
public function foo($bar) {}
}
但是最好重新考虑一下为什么你真的需要这个,并尝试保持类型安全。

关于php - 如何在 PHP 中的子类继承方法中定义更严格的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62930305/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com