PHP: Как передать аргументы дочернего класса __construct () в parent :: __ construct ()? - PullRequest
35 голосов
/ 22 октября 2009

У меня есть класс в PHP, например:

class ParentClass {
    function __construct($arg) {
        // Initialize a/some variable(s) based on $arg
    }
}

У него есть дочерний класс, как таковой:

class ChildClass extends ParentClass {
    function __construct($arg) {
        // Let the parent handle construction. 
        parent::__construct($arg); 
    }
}

Что если по какой-то причине ParentClass нужно изменить, чтобы он принимал более одного необязательного аргумента, который я хотел бы, чтобы мой класс Child предоставлял "на всякий случай"? Если я не перекодирую ChildClass, он будет принимать только один аргумент для конструктора и будет передавать только один этот аргумент.

Является ли это настолько редкой или такой плохой практикой, что обычный случай заключается в том, что ChildClass не должен был бы наследовать от ParentClass, который принимает другие аргументы?

По сути, я видел в Python, где вы можете передать потенциально неизвестное количество аргументов функции через somefunction(*args), где 'args' это массив / итерируемый некоторого вида. Существует ли что-то подобное в PHP? Или мне следует провести рефакторинг этих классов, прежде чем продолжить?

Ответы [ 7 ]

40 голосов
/ 12 апреля 2017

Это можно сделать в PHP> = 5.6 без call_user_func_array() с помощью оператора ... (сплат) :

public function __construct()
{
    parent::__construct(...func_get_args());
}
31 голосов
/ 22 октября 2009

В php есть что-то вроде этого, но немного многословно:

$args = func_get_args();
call_user_func_array(array($this, 'parent::__construct'), $args);
10 голосов
/ 19 февраля 2013

если вы получили ошибку вложенного лимита php, попробуйте это:

$args = func_get_args();
call_user_func_array(array('parent', '__construct'), $args);
3 голосов
/ 03 апреля 2018

Мой способ сделать это (проверено в PHP 7.1):

class ParentClass {
    public function __construct(...$args) {
        print 'Parent: ' . count($args) . PHP_EOL;
    }
}

class ChildClass extends ParentClass {
    public function __construct(...$args) {
        parent::__construct(...$args);
        print 'Child: ' . count($args). PHP_EOL;
    }
}

$child = new ChildClass(1, 2, 3, new stdClass);

//Output: 
//Parent: 4
//Child: 4

Проверьте это https://3v4l.org/csJ68

В этом случае родительский и дочерний элементы имеют одинаковую подпись конструктора. Это также работает, если вы хотите распаковать ваши аргументы в родительском конструкторе:

class ParentClass {
    public function __construct($a, $b, $c, $d = null) {
        print 'Parent: ' . $a .  $b .  $c . PHP_EOL;
    }
}

class ChildClass extends ParentClass {
    public function __construct(...$args) {
        parent::__construct(...$args);
    }
}

$child = new ChildClass(1, 2, 3);

//Output: Parent: 123

Проверьте это https://3v4l.org/JGE1A

Стоит также отметить, что в PHP> = 5.6 вы можете применять типы для функций с переменным числом (скалярные типы в PHP> = 7):

class ParentClass {
    public function __construct(DateTime ...$args) {
        //Do something
    }
}
1 голос
/ 22 октября 2009

Проверьте эти функции на php.net:

.
func_get_args
func_num_args

Кроме того, если вы хотите указать необязательный аргумент, вы можете сделать это:

class ParentClass {
    function __construct($arg, $arg2="Default Value") {
        // Initialize a/some variable(s) based on $arg
    }
}
0 голосов
/ 18 ноября 2011
parent::__construct( func_get_args() );
0 голосов
/ 22 октября 2009

Да, это довольно плохая практика - создавать дочерний класс, который использует аргументы конструктора, отличные от родительского. Особенно в таком языке, как PHP, где он плохо поддерживается.

Конечно, общий способ передачи набора «любых аргументов, которые мы можем когда-либо захотеть» в PHP - это передача одного аргумента, состоящего из массива значений конфигурации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...