在PHP5中,我可以 Select 重载构造函数(以及任何其他方法).但如果我得到这样的代码:

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有来自traits的冲突构造函数定义

我怎么才能把它修好呢?您可以测试我的代码here.

推荐答案

我认为现在唯一能做你想做的就是:

class MyHelloWorld extends Base {

    use SayWorld {
        SayWorld::__construct as private __swConstruct;
    }

    public function __construct($a, $b, $c = 0)
    {
        $this->__swConstruct($a, $b, $c);
    }
}

Edit 2:

基于一年多在PHP中处理特性的经验,我的建议是:avoid writing constructors in traits at all,或者如果必须的话——至少让它们无参数化.让他们具有trait 与建设者通常的 idea 背道而驰,即:constructors should be specific to a class to which they belong.其他一些经过进化的高级语言甚至不支持隐式构造函数继承.这是因为构造函数与类的关系比其他方法强得多.事实上,他们之间的关系如此密切,甚至LSP人也不适用于他们.Scala语言(Java的一个非常成熟和SOLID友好的继承者)的特性,can't have a constructor with parameters.

Edit 1:

PHP5.4.11中有一个bug,它实际上允许对超类方法进行别名.但是PHP开发人员认为这是不允许的,所以我们仍然坚持使用我在上面介绍的那个笨重的解决方案.但这个bug引发了一场关于如何使用它的讨论,我希望它能在future 的版本中成为目标.

与此同时,我一次又一次地遇到同样的问题.我的恼怒随着docblock的参数和行的数量呈指数增长,为了使用这个特性,这些参数和行必须重复很多次.因此,我想出了下面的模式,以便尽可能地坚持干巴巴的规则:

不是像这样重复整个参数集:

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);
    }
}

我编写了一个类似于tuple(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的动态特性,它可以进一步自动化.

Php相关问答推荐

如何在Laravel Controller中存储文本区域值?

为什么调用干预\映像引发错误驱动程序\GD\Driver not found?

如何隐藏x轴图表上的值

WooCommerce购物车中仅允许一个可下载产品

WooCommerce产品按特定元数据的自定义数字排序选项

WooCommerce/WordPress:简单的产品属性显示

在WooCommerce中添加基于类别的固定费用

如何在php中生成包含第100秒的时间序列?

如何使用php一次更新两个数据库中的MySQL表

将WooCommerce WC_Order对象与wp_Schedule_Event一起使用

按列值将二维数组排序为不超过N个的递增组

如果日期是过go 日期,则隐藏事件发布类型

如何在WordPress REST API中判断应用程序密码

拉威尔10有许多通过获取所有祖父母数据的子元素S图像

HTTPPost请求在从php脚本调用时返回404,但在从node.js脚本调用时有效.终结点有效

dyld[45923]:未加载库:/usr/local/opt/libavif/lib/libavif.15dylib

在 Woocommerce 邮箱订单中显示产品 GTIN

PHP 中的curl -F request=@file.xml

转发和非转发呼叫 - 后期静态绑定

Docker: unixodbc.h 没有这样的文件或目录.已安装 unixodbc-dev 时出现pecl install sqlsrv错误