Php 使用不兼容的函数实现接口和错误
我有这个测试脚本:Php 使用不兼容的函数实现接口和错误,php,oop,Php,Oop,我有这个测试脚本: <?php interface A { function myfunction(); } class B implements A { function myfunction($var = "default") { echo $var; } } class C extends B { function myfunction() { echo "myfunction"; } } $c = new C(); $c->m
<?php
interface A
{
function myfunction();
}
class B implements A
{
function myfunction($var = "default")
{
echo $var;
}
}
class C extends B
{
function myfunction()
{
echo "myfunction";
}
}
$c = new C();
$c->myfunction();
$b = new B();
$b->myfunction();
我得到这个错误:
PHP Strict standards: Declaration of C::myfunction() should be compatible with that of B::myfunction() in /var/www/test/index.php on line 16
Strict standards: Declaration of C::myfunction() should be compatible with that of B::myfunction() in /var/www/test/index.php on line 16
myfunctiondefault
为什么这在第一次就奏效了?我预计在这两种情况下都会出现错误…使用接口时,
B
和C
会根据接口声明进行独立验证。C扩展B
并不重要C
间接地实现了A
,并且C::myfunction
与A::myfunction
兼容,因此没有问题B::myfunction
也与A::myfunction
兼容,因此也没有问题
在没有接口的情况下,B::myfunction
是该方法的规范声明,由于它接受一个参数,但重写的C::myfunction
不接受,因此会发出STRICT
警告
基本上,您希望确保此代码正常工作:
if ($obj instanceof <classWhoseInterfaceIExpect>) {
$obj-><interfaceIExpect>();
}
由于A::myfunction
被规范地声明为不接受任何参数,因此上述代码将始终有效。但是,如果没有接口:
if ($obj instanceof B) {
$obj->myfunction('foo');
}
如果B::myfunction
是接受参数的规范声明,但是C
提供了一个不接受参数的实现,那么您已经创建了冲突。因此发出警告。这是为了回答这个问题,为什么它会这样工作,这是PHP的思想解释
警告:是的,即使您使用该接口,也会产生相同的冲突:
interface A { ... }
class B implements A { ... }
class C extends B { ... } // conflicting implementation to B
$obj = new C;
if ($obj instanceof B) {
$obj->myfunction('foo');
}
C
既是A
和B
的实例,但它不能同时与myfunction
的两种实现兼容。这是创建两个冲突实现的问题。PHP是否也应该在这里发出警告是有争议的。PHP不能既吃蛋糕又吃蛋糕。它的类型系统可以帮助您尽早发现某些错误;它当然不是完美的,也不能保护你从所有可能的角度射中自己的脚
如果您想避免此类问题,基本上不应该更改方法签名。或者说,这种变化正在向下蔓延;这意味着每个扩展类都与其直接父类的方法签名兼容。因此C::myfunction
应至少接受一个可选参数。也许PHP应该捕捉到这种情况,也许它可以被认为是一个bug,您在所有情况下都没有得到警告。同样,这是有争议的,您应该避免从一开始就陷入这种情况。问题:您使用的是什么PHP版本?如下所示:在PHP版本5.4.6上运行,打印:myfunctiondefault
@Darren这只是一个严格的错误,显然它在您的服务器上被禁用,因为我有相同的错误,我使用的是5.3.10,但两个版本的代码都可以运行。我只想知道为什么我的第一个版本被认为是正确的,而我的第二个版本被认为是错误的。请注意:这个错误在PHP版本5.3.*中给出,但在PHP 5.4.0(及更高版本)中被更改(修复了?)。在这两种情况下都没有给出错误。
if ($obj instanceof B) {
$obj->myfunction('foo');
}
interface A { ... }
class B implements A { ... }
class C extends B { ... } // conflicting implementation to B
$obj = new C;
if ($obj instanceof B) {
$obj->myfunction('foo');
}