Php类型提示不与接口和抽象类相处?

2022-08-30 20:58:41

我认为在代码示例中看到问题比首先编写问题要容易得多。这是我的php代码:

<?php

interface AnInterface
{
        public function method();
}    

class AClass implements AnInterface
{
        public function method()
        {
                echo __METHOD__;
        }
}    

abstract class AnAbstractClass
{
        abstract public function method( AnInterface $Object );
}

class ConcreteClass extends AnAbstractClass
{
        public function method( AClass $Object )
        {
                $Object->method();
        }
}

$Object1 = new ConcreteClass();
$Object2 = new AClass();

$Object1->method( $Object2 );

上面的代码会导致以下错误:

致命错误:ConcreteClass::method() 的声明必须与 AnAbstractClass::method() 的声明兼容

问题是php似乎没有将AnAbstractClass::method和ConcreteClass::method的签名识别为兼容。我做错了什么吗?谢谢!


答案 1

php似乎没有识别和的签名是兼容的。AnAbstractClass::methodConcreteClass::method

PHP是正确的,它们兼容。通过只允许将 (或其子类) 的实例传递给 ,您违反了提供以下内容的契约:它的任何子类都必须接受作为其 的参数。AClassConcreteClass::methodAnAbstractClassAnInterfacemethod()

如果你的例子有效,并且我有另一个类实现,我们将遇到这样的情况,根据,应该接受的实例,而根据,它不应该。BClassAnInterfaceAnAbstractClassmethod()BClassConcreteClass

更改 的签名以匹配 。ConcreteClass::methodAnAbstractClass::method


答案 2

下面是一个示例,说明了为什么不允许这样做:

<?php
class BClass implements AnInterface { }

function moo(AnAbstractClass $abstract)
{
    $b = new BClass();
    $abstract->method($b);
}

这将是一个有效的代码,但是如果您将 a 传递给 moo,它将失败,因为它的方法不允许 .ConcreteClassConcreteClass::methodBClass

它很复杂,但如果你看到一个例子,它更容易理解。


推荐