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() );
精彩评论