php方法重写:Declaration of should be compatible with that

<?php
// this code does trigger a strict message
error_reporting( E_ALL | E_STRICT );

class cc extends c { function test() { return null; } }
class c { function test( $a ) { return 1; } }

$cc = new cc();
?>
< ?php
// this code does NOT trigger a strict message
error_reporting( E_ALL | E_STRICT );

class c { function test( $a ) { return 1; } }
class cc extends c { function test() { return null; } }

$cc = new cc();
?>

并且讨论了出错的情况多半是由于用_autoload()对类进行自动的include,导致基类的定义在后面,子类定义在前面。

我看了下自己的代码,虽然确实也用到了autoload,但是都是显式的先导入了几个基类,并不存在这样的情况,而且将上面的正反例子试了一下,都会出现E_STRICT的警告。


再看例子

代码如下  
<?php
abstract class A {
// 方法无参数
public static function foo(){ echo 'bar'; }
}

abstract class B extends A {
// 方法有参数
public static function foo($str){ echo $str; }
}
?>

闪电似的

如上面的代码:类A中的foo方法无参数,类B在继承A后重写foo方法时加入了参数,因此会产生一个类似下面E_STRICT级别的警告:

Strict standards: Declaration of ... should be compatible with that of

代码如下  
<?php
abstract class A {
// 方法无参数
public static function foo(){ echo 'bar'; }
}

abstract class B extends A {
// 方法有参数
public static function foo($str = NULL){ echo $str; }
}
?>

类B在重写foo方法时为新加入的参数指定一个默认值即可

真正原因:

其实如果子类重写方法的参数和基类不一样,只要给参数个默认值,使得编译器认为参数可以为空,保持重写方法与基类方法的函数签名相同就可以了。
经常用JAVA的同学肯定知道,在JAVA或者C++中,重写方法的函数签名本应该就和基类函数是一致的,我认为这也是符合自然规律的,因为override本来就是覆盖的意思嘛,既然覆盖了,那么就应该和原函数一致,不然怎么能“盖”的住呢~并且方法的重写多用在重写虚函数或者更明白的说就是重写接口的函数,如果重写的时候函数签名都不一致了,还要接口干嘛呢。。。
所以PHP的新版本中,我觉得定义这个E_STRICT的警告错误是很有用处的,要提醒程序员自己的重写方法到底对不对。

最后还是鄙视一下上面那些抄来抄去的帖子,如果某个语言连基类和子类定义的顺序都不能打乱,说明这个编译器非常有问题了,显然是bug。

posted @ 2018-01-23 10:30  追忆丶年华  阅读(1867)  评论(0编辑  收藏  举报