在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);
Run Code Online (Sandbox Code Playgroud)
我有一个错误:
致命错误:MyHelloWorld具有来自特征的碰撞构造函数定义
我该怎么解决它?你可以在这里测试我的代码.
Mac*_* Sz 106
我认为现在做你想做的唯一方法是:
class MyHelloWorld extends Base {
use SayWorld {
SayWorld::__construct as private __swConstruct;
}
public function __construct($a, $b, $c = 0)
{
$this->__swConstruct($a, $b, $c);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
基于在PHP中处理特征超过一年的建议,我的建议是:避免在构造函数中编写特性,或者如果必须的话 - 至少使它们无参数化.将它们置于特征中则违背了构造函数的概念,即:构造函数应该特定于它们所属的类.其他演进的高级语言甚至不支持隐式构造函数继承.这是因为构造函数与其他方法相比具有更强的关系.事实上,他们之间的联系非常紧密,甚至LSP都不适用于他们.Scala语言中的特性(一种非常成熟且对SOLID友好的Java继承者)不能有带参数的构造函数.
编辑1:
PHP 5.4.11中存在一个错误,它实际上允许别名超类方法.但这被PHP开发人员认为是禁忌,所以我们仍然坚持上面提到的那种繁琐的解决方案.但是这个bug引发了关于可以用它做什么的讨论,我希望它将成为未来版本的目标.
与此同时,我一遍又一遍地遇到同样的问题.我的烦恼随着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);
}
}
Run Code Online (Sandbox Code Playgroud)
我写一个类很像元组(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;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:对于大量的元组构造函数参数以及使用元组的更多类,这种模式当然更有用.
它可以通过使用PHP的动态特性进一步自动化.
尝试:
use SayWorld {
Base::__construct insteadof SayWorld;
}
Run Code Online (Sandbox Code Playgroud)
参考:PHP文档
旧帖子,但是,如果这对任何人有帮助:
我也遇到过类似的情况,但决定使用稍微不同的方法。我正在编写一个 WordPress 插件,想要传递插件信息(版本、名称、文本域等),但不想在重构或扩展另一个类时四处更改每个文件,因此我使用构造函数创建了一个特征它只是调用一个 init 函数来执行特定于类的操作。
trait HasPluginInfoTrait{
public function __construct() {
$this->plugin_name = PLUGIN_NAME;
$this->version = PLUGIN_VERSION;
if ( method_exists( $this, 'init' ){
$this->init();
}
}
}
class SampleClass {
use HasPluginInfoTrait;
private function init(){
// Code specific to SampleClass
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
41294 次 |
| 最近记录: |