简体   繁体   English

PHP:如何将子类 __construct() 参数传递给 parent::__construct()?

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

I have a class in PHP like so:我在 PHP 中有一个类,如下所示:

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

It has 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"?如果出于某种原因,ParentClass 需要更改以采用多个可选参数,我希望我的 Child 类“以防万一”提供该参数怎么办? 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.除非我重新编码 ChildClass,否则它只会将一个参数传递给构造函数,并且只会传递那个参数。

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?这是罕见的还是糟糕的做法,以至于通常的情况是 ChildClass 不需要从采用不同参数的 ParentClass 继承?

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.本质上,我在 Python 中看到过,您可以通过somefunction(*args)将潜在未知数量的参数传递给函数,其中 'args' 是某种数组/可迭代对象。 Does something like this exist in PHP? 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 : 这可以通过使用... (splat)运算符在没有call_user_func_array()的PHP> = 5.6中完成:

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

There is something like this in php, though a bit verbose: 在PHP中有这样的东西,虽然有点冗长:

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

if you get php nested limit error, try this: 如果你得到php嵌套限制错误,试试这个:

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

My way of doing it (tested in PHP 7.1): 我的方式(在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 测试它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 测试它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): 值得注意的是,在PHP> = 5.6中,您可以强制执行可变函数的类型(PHP中的标量类型> = 7):

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

Check out these functions on php.net: 在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. 特别是在PHP这样的语言中,它支持得很差。

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. 当然,在PHP中传递一组“我们可能想要的任何参数”的通用方法是传递一个由一组配置值组成的参数。

PHPStorm Inspection suggests to use the argument unpacking feature instead of call_user_func_array(). PHPStorm Inspection建议使用参数解包功能而不是call_user_func_array()。 Apart less magic, the feature is faster. 除了神奇之外,功能更快。 Source: https://wiki.php.net/rfc/argument_unpacking 资料来源: https//wiki.php.net/rfc/argument_unpacking

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM