PHP:类方法参数的类型声明

时间:2015-12-16 14:40:36

标签: php

当我试图运行以下代码时,我得到了E_COMPILE_ERROR

<?php

interface DataInterface
{
    public function get();
}

interface ServiceInterface
{
    public function save(DataInterface $data);
}

class Data implements DataInterface
{
    public function get()
    {
        return 'data';
    }
}

class Service implements ServiceInterface
{
    public function save(Data $data)
    {//the problem is here^^
        var_dump($data->get());
    }   
}

$service = new Service();
$data = new Data();
$service->save($data);

Data类是DataInterface接口的实现。我想知道为什么这段代码无法编译?文档说明有效类型必须是给定类或接口名称的实例。 (http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration)。

$data = new Data();
var_dump($data instanceof DataInterface); //true;

据我所知,如果声明的方法参数类型是实现预期接口的类,则此类型满足需求(实现所有方法)并且签名应该匹配。

2 个答案:

答案 0 :(得分:2)

实施Service需要

ServiceInterface ServiceInterface指定save必须接受DataInterfaceService::save接受Data而不是DataInterface。这不是同一类型,实现与接口声明不兼容。

当您致电 Service::save时,非常重要,$datainstanceof DataInterface;而不是在声明方法签名时。

为了更深入地了解这一点:接口以这种方式使用:

function foo(ServiceInterface $service) {
   $service->save($something);
}

换句话说,其他一些代码将会收到implements ServiceInterface的内容。它不知道或关心$service是什么,只要它实现ServiceInterface中指定的已知合同即可。并且ServiceInterface指定可以将任何DataInterface传递给$service::save()而不是Data 实例。 $something可以是implements DataInterface的任何其他对象。让Service::save仅接受Data个实例会破坏该合同并导致运行时错误。

答案 1 :(得分:0)

运行代码时出现以下异常:

PHP Fatal error:  Declaration of Service::save() must be compatible with ServiceInterface::save(DataInterface $data) in test.php on line 22
PHP Stack trace:
PHP   1. {main}() test.php:0

Fatal error: Declaration of Service::save() must be compatible with ServiceInterface::save(DataInterface $data) in test.php on line 22

Call Stack:
    0.0002     130808   1. {main}() test.php:0

..并且您的问题非常明确:Service :: save()的声明是错误的。它试图接受Date,而它试图覆盖的函数(ServiceInterface::save)需要DateInterface

您应该更改Service :: save()的签名以接受DateInterface。您仍然可以将Date对象传递给它,但您不能强制它作为Date对象。如果你想要一个仅占用Date个对象(及其子类)的方法,你需要给它一个新的名字。