我如何获得一个PHP类的构造函数来调用其父类的构造函数
我需要在PHP中有一个类构造函数,而不用调用父类的构造函数来调用其父类(祖父类)的构造函数。
// main class that everything inherits class Grandpa { public function __construct() { } } class Papa extends Grandpa { public function __construct() { // call Grandpa's constructor parent::__construct(); } } class Kiddo extends Papa { public function __construct() { // THIS IS WHERE I NEED TO CALL GRANDPA'S // CONSTRUCTOR AND NOT PAPA'S } }
我知道这是一个奇怪的事情,我试图find一种手段,但没有闻起来不好,但我很好奇,如果有可能的话。
编辑
我想我应该张贴所选答案的理由。 原因是; 这是最优雅的解决scheme,想要在保留所有的价值的同时调用“祖父母”的构造函数的问题。 这当然不是最好的方法,也不是OOP友好的,但这不是问题的要求。
对于晚些时候遇到这个问题的人 – 请find另一个解决scheme 。 我能find一个更好的方法,不会对class级结构造成严重破坏。 所以你应该。
丑陋的解决方法是将一个布尔parameter passing给Papa,表明您不希望parsing包含在其构造函数中的代码。 即:
// main class that everything inherits class Grandpa { public function __construct() { } } class Papa extends Grandpa { public function __construct($bypass = false) { // only perform actions inside if not bypassing if (!$bypass) { } // call Grandpa's constructor parent::__construct(); } } class Kiddo extends Papa { public function __construct() { $bypassPapa = true; parent::__construct($bypassPapa); } }
你必须使用Grandpa::__construct()
,没有其他的快捷方式。 另外,这也破坏了Papa
类的封装 – 在Papa
阅读或者工作时,假设__construct()
方法在施工期间被调用应该是安全的,但是Kiddo
类不会这样做。
class Grandpa { public function __construct() {} } class Papa extends Grandpa { public function __construct() { //call Grandpa's constructor parent::__construct(); } } class Kiddo extends Papa { public function __construct() { //this is not a bug, it works that way in php Grandpa::__construct(); } }
另一个不使用标志的选项可能适用于您的情况:
<?php // main class that everything inherits class Grandpa { public function __construct(){ $this->GrandpaSetup(); } public function GrandpaSetup(){ $this->prop1 = 'foo'; $this->prop2 = 'bar'; } } class Papa extends Grandpa { public function __construct() { // call Grandpa's constructor parent::__construct(); $this->prop1 = 'foobar'; } } class Kiddo extends Papa { public function __construct() { $this->GrandpaSetup(); } } $kid = new Kiddo(); echo "{$kid->prop1}\n{$kid->prop2}\n";
我最终提出了一个解决问题的替代解决scheme。
- 我创造了一个延续爷爷的中级课程。
- 然后,爸爸和基德都延续了这堂课。
- Kiddo需要Papa的一些中间function,但不喜欢它的构造函数,所以类有附加function,并扩展它。
我已经upvoted另外两个答案,提供了一个丑陋的问题有效但丑陋的解决scheme:)
美丽的解决scheme
<?php class Grandpa { public function __construct() { echo "Grandpa's constructor called\n"; } } class Papa extends Grandpa { public function __construct() { echo "Papa's constructor called\n"; // call Grandpa's constructor parent::__construct(); } } class Kiddo extends Papa { public function __construct() { echo "Kiddo's constructor called\n"; $reflectionMethod = new ReflectionMethod(get_parent_class(get_parent_class($this)), '__construct'); $reflectionMethod->invoke($this); } } $kiddo = new Kiddo(); $papa = new Papa();
对此有一个更简单的解决scheme,但是它要求您确切知道您的当前类已经经历了多lessinheritance。 幸运的是,get_parent_class()的参数允许你的类数组成员作为一个string的类名以及一个实例本身。
请记住,这也固有地依赖于静态地调用类__construct()方法,尽pipe在inheritance对象的实例范围内,这种特殊情况下的差异可以忽略不计(PHP,PHP)。
考虑以下:
class Foo { var $f = 'bad (Foo)'; function __construct() { $this->f = 'Good!'; } } class Bar extends Foo { var $f = 'bad (Bar)'; } class FooBar extends Bar { var $f = 'bad (FooBar)'; function __construct() { # FooBar constructor logic here call_user_func(array(get_parent_class(get_parent_class($this)), '__construct')); } } $foo = new FooBar(); echo $foo->f; #=> 'Good!'
同样,由于debug_backtrace()的局限性,在不知道已经发生了多lessinheritance的情况下,这不是一个可行的解决scheme,但是在受控环境下,它可以按预期工作。
我同意“太多的PHP”,试试这个:
class Grandpa { public function __construct() { echo 'Grandpa<br/>'; } } class Papa extends Grandpa { public function __construct() { echo 'Papa<br/>'; parent::__construct(); } } class Kiddo extends Papa { public function __construct() { // THIS IS WHERE I NEED TO CALL GRANDPA'S // CONSTRUCTOR AND NOT PAPA'S echo 'Kiddo<br/>'; Grandpa::__construct(); } } $instance = new Kiddo;
我得到了预期的结果:
老兄
爷爷
这是一个function不是bug,请检查以供参考:
https://bugs.php.net/bug.php?id=42016
这只是它的工作方式。 如果它看到它来自正确的上下文,这个调用版本不强制执行静态调用。
相反,它会保持$这个并且对它感到满意。
parent :: method()以相同的方式工作,您不必将该方法定义为静态,但可以在相同的上下文中调用该方法。 试试这个更有趣的:
class Grandpa { public function __construct() { echo 'Grandpa<br/>'; Kiddo::hello(); } } class Papa extends Grandpa { public function __construct() { echo 'Papa<br/>'; parent::__construct(); } } class Kiddo extends Papa { public function __construct() { // THIS IS WHERE I NEED TO CALL GRANDPA'S // CONSTRUCTOR AND NOT PAPA'S echo 'Kiddo<br/>'; Grandpa::__construct(); } public function hello() { echo 'Hello<br/>'; } } $instance = new Kiddo;
它也按预期工作:
老兄
爷爷
你好
但是如果你尝试初始化一个新的爸爸,你会得到一个E_STRICT错误:
$papa = new Papa;
严格标准:非静态方法Kiddo :: hello()不应该被静态调用,假设$ this来自不兼容的上下文
您可以使用instanceof来确定您是否可以在父方法中调用Children :: method():
if ($this instanceof Kiddo) Kiddo::hello();
您可以从您想要的位置调用Grandpa :: __构造,$ this关键字将引用您当前的类实例。 但是要小心这个方法,你不能从这个其他的上下文访问受保护的属性和当前实例的方法,只能访问公共元素。 =>所有工作和官方支持 。
例
// main class that everything inherits class Grandpa { public function __construct() { echo $this->one; // will print 1 echo $this->two; // error cannot access protected property } } class Papa extends Grandpa { public function __construct() { // call Grandpa's constructor parent::__construct(); } } class Kiddo extends Papa { public $one = 1; protected $two = 2; public function __construct() { Grandpa::__construct(); } } new Kiddo();
好的,又一个丑陋的解决scheme:
在Papa中创build一个函数,如:
protected function call2Granpa() { return parent::__construct(); }
然后在Kiddo中使用:
parent::call2Granpa();
//而不是在Papa中调用构造函数。
我认为它可以工作…我还没有testing,所以我不知道如果对象创build正确。
我用这种方法,但与非构造函数。
<?php class grand_pa { public function __construct() { echo "Hey I am Grand Pa <br>"; } } class pa_pa extends grand_pa { // no need for construct here unless you want to do something specifically within this class as init stuff // the construct for this class will be inherited from the parent. } class kiddo extends pa_pa { public function __construct() { parent::__construct(); echo "Hey I am a child <br>"; } } new kiddo(); ?>
当然,这期望你不需要在pa_pa的构造中做任何事情。 运行这将输出:
嘿,我是大霸王嘿,我是一个孩子
关于php的有趣的细节:扩展类可以使用静态事物中父类的非静态函数。 外面你会得到一个严格的错误。
error_reporting(E_ALL); class GrandPa { public function __construct() { print("construct grandpa<br/>"); $this->grandPaFkt(); } protected function grandPaFkt(){ print(">>do Grandpa<br/>"); } } class Pa extends GrandPa { public function __construct() { parent::__construct(); print("construct Pa <br/>"); } public function paFkt(){ print(">>do Pa <br>"); } } class Child extends Pa { public function __construct() { GrandPa::__construct(); Pa::paFkt();//allright //parent::__construct();//whatever you want print("construct Child<br/>"); } } $test=new Child(); $test::paFkt();//strict error
所以在扩展类(Child)中可以使用
parent::paFkt();
要么
Pa::paFkt();
访问父母(或grandPa's)(非私人)function。
外部类def
$test::paFkt();
将严重错误(非静态函数)。
// main class that everything inherits class Grandpa { public function __construct() { $this->___construct(); } protected function ___construct() { // grandpa's logic } } class Papa extends Grandpa { public function __construct() { // call Grandpa's constructor parent::__construct(); } } class Kiddo extends Papa { public function __construct() { parent::___construct(); } }
注意“___construct”不是一些神奇的名字,你可以称之为“doGrandpaStuff”。
class Grandpa { public function __construct() { echo"Hello Kiddo"; } } class Papa extends Grandpa { public function __construct() { } public function CallGranddad() { parent::__construct(); } } class Kiddo extends Papa { public function __construct() { } public function needSomethingFromGrandDad { parent::CallGranddad(); } }
从PHP 7ü可以使用
parent::parent::__construct();