В 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 есть конфликтующие определения конструктора, исходящие из признаков
Как я могу это исправить? Здесь вы можете проверить свой код.
Я думаю, что теперь единственный способ сделать то, что вы хотите:
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 (очень зрелый и SOLID- дружественный преемник Java) не могут иметь конструктор с параметрами .
Изменить 1:
В PHP 5.4.11 произошла ошибка , которая фактически разрешала псевдоним метода суперкласса. Но разработчики PHP это считали не-нет, поэтому мы все еще придерживаемся этого громоздкого решения, которое я представил выше. Но эта ошибка подняла дискуссию о том, что с этим можно сделать, и я надеюсь, что она будет нацелена на будущие выпуски.
Тем временем я сталкивался с одной и той же проблемой снова и снова. Мое раздражение экспоненциально возрастало с количеством параметров и линий докблока, которые нужно было повторять много раз, чтобы использовать этот признак. Поэтому я придумал следующую схему, чтобы придерживаться правила 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.
Пытаться:
use SayWorld { Base::__construct insteadof SayWorld; }
Ссылка: PHP-документы