如何在PHP> = 5.4中的特征内重载类构造函数 [英] How to overload class constructor within traits in PHP >= 5.4

查看:79
本文介绍了如何在PHP> = 5.4中的特征内重载类构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In PHP 5, I can to overload constructors (and any others methods). But if I get some code like this:

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

Fatal error: MyHelloWorld has colliding constructor definitions coming from traits

我该如何解决?您可以在此处进行测试.

How can I to fix it? You can test my code here.

推荐答案

我认为目前唯一可以做自己想做的方法是:

I think for now the only way to do what you want is:

class MyHelloWorld extends Base {

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

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

基于一年多使用PHP处理特征的经验,我的建议是:完全避免使用特征编写构造函数,或者如果必须的话-至少使它们成为无参数的.使它们具有特征通常会违背构造函数的想法,即构造函数应特定于它们所属的类.其他经过发展的高级语言甚至不支持隐式构造函数继承.这是因为构造函数与类的关系比其他方法牢固得多.实际上,它们之间的联系是如此紧密,以至于 LSP 也不适用于它们. Scala语言的特征(非常成熟且 SOLID 友好的继承者) Java),不能有带参数的构造函数.

My advice, based on over a year of dealing with traits in PHP, is: avoid writing constructors in traits at all, or if you must - at least make them parameterless. Having them in traits goes against the idea of constructors in general, which is: constructors should be specific to a class to which they belong. Other, evolved high-level languages don't even support implicit constructor inheritance. This is because constructors have far more stronger relation to the class then other methods. In fact they have so strong relation, that even the LSP does not apply to them. The traits in Scala language (a very mature and SOLID-friendly successor of Java), can't have a constructor with parameters.

PHP 5.4.11中存在一个 bug ,实际上允许别名一个超类方法.但是,PHP开发人员认为这是不可以的,因此我们仍然对我上面介绍的那种繁琐的解决方案感到困惑.但是该错误引发了有关如何解决此问题的讨论,我希望它将在将来的发行版中成为针对性.

There was a bug in PHP 5.4.11, which actually allowed to alias a superclass method. But this was considered a no-no by the PHP developers, so we are still stuck with that cumbersome solution which I presented above. But that bug raised a discussion about what can be done with this, and I'm hoping it will be targeted in future releases.

与此同时,我一遍又一遍地遇到了同样的问题.使用docblock的参数和行的数量激增了我的怒气,为了使用该特性,必须重复很多次.因此,我想出了以下模式,以便尽可能地坚持DRY规则:

Meanwhile I came across the same problem over and over again. My irritation raised exponentially with the number of parameters and lines of docblock which had to be repeated a lot of times in order to use the trait. So I came up with the following pattern in order to stick to the DRY rule as much as I could:

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

Instead of repeating entire set of parameters like this:

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 用户),并改用它无限的参数列表:

I write a class much like a tuple (concept familiar to C# and Python users), and use it instead of an endless list of parameters:

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

注意:这种模式在使用大量tuple的构造函数参数和使用tuple的更多类时当然更有用.

Note: this pattern is of course more useful with a larger amount of tuple's constructor parameters, and more classes using the tuple.

可以利用PHP的动态特性进一步实现自动化.

It can be automated further with the use of PHP's dynamic nature.

这篇关于如何在PHP> = 5.4中的特征内重载类构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆