当我试图运行以下代码时,我得到了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;
据我所知,如果声明的方法参数类型是实现预期接口的类,则此类型满足需求(实现所有方法)并且签名应该匹配。
答案 0 :(得分:2)
Service
需要 ServiceInterface
ServiceInterface
指定save
必须接受DataInterface
但Service::save
接受Data
而不是DataInterface
。这不是同一类型,实现与接口声明不兼容。
当您致电 Service::save
时,非常重要,$data
是instanceof 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
个对象(及其子类)的方法,你需要给它一个新的名字。