我认为现在做你想做的唯一方法是:
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 中的特征,我的建议是:完全避免在特征中编写构造函数,或者如果必须 - 至少使它们无参数。将它们放在特征中违背了一般构造函数的想法,即:构造函数应该特定于它们所属的类。其他进化的高级语言甚至不支持隐式构造函数继承。这是因为构造函数与类的关系比其他方法强得多。事实上,它们之间的关系如此之强,以至于连LSP都不适用于它们。Scala 语言中的特征(Java 的一个非常成熟且对SOLID友好的继承者),不能有带参数的构造函数。
编辑1:
PHP 5.4.11 中有一个错误,它实际上允许为超类方法设置别名。但是 PHP 开发人员认为这是一个禁忌,所以我们仍然坚持我上面介绍的那个繁琐的解决方案。但是那个错误引发了关于可以用它做什么的讨论,我希望它会在未来的版本中成为目标。
与此同时,我一遍又一遍地遇到同样的问题。我的愤怒随着 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 的动态特性进一步自动化。