如何在PHP> = 5.4中重载特征中的类构造函数
在PHP 5中,我可以重载构造函数(和其他方法)。 但是,如果我得到这样的代码:
class Base { public function __construct($a, $b) { echo $a+$b; } public function sayHello() { echo 'Hello '; } } trait SayWorld { public function __construct($a, $b, $c = 0) { echo (int)$c * ($a+$b); } public function sayHello($a = null) { parent::sayHello(); echo 'World!'.$a; } } class MyHelloWorld extends Base { use SayWorld; } $o = new MyHelloWorld(2, 3); $o->sayHello(1);
我有一个错误:
致命错误:MyHelloWorld碰撞来自特质的构造函数定义
我该如何解决它? 你可以在这里testing我的代码。
我认为现在做你想做的唯一方法是:
class MyHelloWorld extends Base { use SayWorld { SayWorld::__construct as private __swConstruct; } public function __construct($a, $b, $c = 0) { $this->__swConstruct($a, $b, $c); } }
编辑2:
基于在PHP中处理特征一年多的时间,我的build议是: 避免把构造函数写成特性 ,或者如果你必须 – 至less使它们无参数。 具有他们的特质违背了一般的build设者的想法,即build设者应该专门针对他们所属的类 。 其他,进化的高级语言甚至不支持隐式的构造函数inheritance。 这是因为构造函数与类和其他方法的关系要强得多。 事实上他们有很强的关系,连LSP也不适用于他们。 Scala语言中的特性(Java的一个非常成熟和SOLID友好的inheritance者) 不能拥有带参数的构造函数 。
编辑1:
在PHP 5.4.11中有一个错误 ,它实际上允许别名超类方法。 但是这被PHP开发者认为是不可能的,所以我们仍然坚持上面提到的这个繁琐的解决scheme。 但是,这个错误提出了一个关于可以做什么的讨论,我希望它将在未来的版本中被定位。
同时我一遍又一遍地遇到同样的问题。 为了使用这个特性,我不得不多次重复docblock的参数和行数。 所以我提出了以下模式,以便尽可能地坚持DRY规则:
而不是像这样重复整套参数:
trait SayWorld { /** * This is a valid docblock. * * @param int $a Doc comment. * @param int $b Doc comment. */ public function __construct($a, $b) { echo (int)$c * ($a+$b); } } class MyHelloWorld extends Base { use SayWorld { SayWorld::__construct as private __swConstruct; } /** * Repeated and unnecessary docblock. * * @param int $a Doc comment. * @param int $b Doc comment. * @param int $c Doc comment. */ public function __construct($a, $b, $c = 0) { $this->__swConstruct($a, $b); } }
我写了一个类很像一个类( C#和Python用户熟悉的概念),并使用它,而不是一个无尽的参数列表:
class SayWorldConstructTuple { public $a; public $b; public function __construct($a, $b) { $this->a = $a; $this->b = $b; } } class MyHelloWorld extends Base { use SayWorld { SayWorld::__construct as private __swConstruct; } /** * New and valid docblock. * * @param SayWorldConstructTuple $Tuple * @param int $c Additional parameter. */ public function __construct(SayWorldConstructTuple $Tuple, $c = 0) { $this->__swConstruct($Tuple->a, $Tuple->b); $this->c = $c; } }
注意:这个模式当然更适用于大量的元组的构造函数参数,以及更多使用元组的类。
它可以通过使用PHP的dynamic特性进一步自动化。
尝试:
use SayWorld { Base::__construct insteadof SayWorld; }
Ref: PHP Docs