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');
}