开发者

PHP: How to Pass child class __construct() arguments to parent::__construct()?

I have a class in PHP like so:

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

It ha开发者_StackOverflow中文版s a child class, as such:

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

What if, for some reason, the ParentClass needs to change to take more than one optional argument, which I would like my Child class to provide "just in case"? Unless I re-code the ChildClass, it will only ever take the one argument to the constructor, and will only ever pass that one argument.

Is this so rare or such a bad practice that the usual case is that a ChildClass wouldn't need to be inheriting from a ParentClass that takes different arguments?

Essentially, I've seen in Python where you can pass a potentially unknown number of arguments to a function via somefunction(*args) where 'args' is an array/iterable of some kind. Does something like this exist in PHP? Or should I refactor these classes before proceeding?


This can be done in PHP >= 5.6 without call_user_func_array() by using the ... (splat) operator:

public function __construct()
{
    parent::__construct(...func_get_args());
}


There is something like this in php, though a bit verbose:

$args = func_get_args();
call_user_func_array(array($this, 'parent::__construct'), $args);


if you get php nested limit error, try this:

$args = func_get_args();
call_user_func_array(array('parent', '__construct'), $args);


My way of doing it (tested in 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

Test it https://3v4l.org/csJ68

In this case, the parent and the child have the same constructor signature. It also works if you want to unpack your arguments in the parent constructor:

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

Test it https://3v4l.org/JGE1A

It is also worth noticing that in PHP >= 5.6 you can enforce types for variadic functions (scalar types in PHP >= 7):

class ParentClass {
    public function __construct(DateTime ...$args) {
        //Do something
    }
}


Check out these functions on php.net:

func_get_args
func_num_args

Also, if you want to make an optional argument, you can do this:

class ParentClass {
    function __construct($arg, $arg2="Default Value") {
        // Initialize a/some variable(s) based on $arg
    }
}


Yeah, it's pretty bad practice to make a child class that uses different constructor arguments from the parent. Especially in a language like PHP where it's poorly supported.

Of course, the generic way to pass a set of "whatever arguments we might ever want" in PHP is to pass a single argument consisting of an array of configuration values.


parent::__construct( func_get_args() );
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜