自动摘要
正在生成中……
重构了项目的部分代码,发现有个任务在开发机器上运行正常 (PHP-CLI
模式运行),更新到正式服务器后却没有运行,尝试手动运行,也没有任何输出,毫无头绪,对代码进行了分析排查,可以把代码简化成这样的形式,文件名test.php
。
<?php
//test.php
error_reporting(E_ALL);
ini_set( 'display_errors', 'On' );
abstract class A1 {
function hello($args){
echo "hello $args";
}
abstract function command($args);
}
abstract class A2 extends A1{
function hi($args){
echo "hi $args";
}
abstract function command($args);
}
class A3 extends A2 {
function command($args){
$this->hi($args);
echo PHP_EOL;
$this->hello($args);
}
}
$obj = new A3();
$obj->command('a');
在开发机器上,PHP版本 7.4.1
, php test.php
正常输出结果:
hi a
hello a
而在正式服务器上, PHP版本是7.1.14
,同样的例行,没有任何输出,直接结束,其实是出现了致命错误,虽然脚本设置了error_reporting(E_ALL);
和 ini_set( 'display_errors', 'On' );
好像没什么用。。。
换成命令 php -d display_errors=1 -f test.php
这时才会输出错误信息:
Fatal error: Can't inherit abstract function A1::command() (previously declared abstract in A2) in ……
解决的方法很简单,就是去掉 A2的 abstract function command($args);
Stackoverflow 上有人对这个问题进行了解答:
Try changing your intermediate class to:
abstract class CssElem extends Css {
// abstract protected function parse($data); // <-- take this away
}
See also this comment in the docs.
Quoting from the comment:
An abstract class that extends an abstract class can pass the buck to its child classes when it comes to implementing the abstract methods of its parent abstract class.
It seems however that this will be allowed in the next PHP version 7.2:
It is now allowed to override an abstract method with another abstract method in a child class. (https://wiki.php.net/rfc/allow-abstract-function-override)
重点是这段:
An abstract class that extends an abstract class can pass the buck to its child classes when it comes to implementing the abstract methods of its parent abstract class.
继承抽象父类的抽象类,当它在实现父类的抽象方法时可以(直接)传递这个标志(抽象方法)到他的子类???也就是不需要再写一个相同的抽象方法的意思?有点绕口,大概是这个意思,但是在PHP7.2版本
之后它又允许了这个行为,可以在抽象子类写一个相同名称的抽象方法。
然后我又搜索了关于抽象类/抽象方法的其他内容,找到另一篇文章:
下面这段代码:
abstract class Animal
{
abstract public function run(\stdClass $speed);
}
abstract class Mammal extends Animal
{
abstract public function run($speed);
}
class Lion extends Mammal
{
public function run($speed)
{
return "Runs $speed km/h";
}
}
在php 7.1
及之前的版本都会报错:
Fatal error: Can't inherit abstract function Animal::run() (previously declared abstract in Mammal
不但不能覆写相同的抽象方法,也不能变更参数类型,即 full-featured type variance
在PHP7.1之前都是不完全的,PHP7.2
之后才支持。