我如何获得一个PHP类的构造函数调用它的父的父类的构造(How do I get a PHP cla

2019-07-22 18:08发布

我需要有一个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
    }
}

我知道这是做一个奇怪的事情,我试图找到一种不臭,但尽管如此,我很好奇,如果有可能的手段。

编辑

我想我应该张贴所选答案的理由。 其原因是; 它最优雅的solutionto想称之为“祖父母”的构造,同时保留所有的值的问题。 这当然不是最好的方法也不是OOP友好的,但是这不是问题被问。

对于任何人碰到这个问题即将在以后的日子- 请找其他的解决方案 。 我能找到一个更好的办法,没有对阶级结构造成严重破坏。 所以,你应该。

Answer 1:

丑陋的解决办法是通过一个布尔参数去爸爸表明您不希望解析包含在它的构造函数的代码。 即:

// 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);
    }
}


Answer 2:

您必须使用Grandpa::__construct()有没有其他的捷径吧。 此外,该遗址中的封装Papa类-阅读或工作时Papa ,它应该是安全的假设__construct()方法,将施工过程中被调用,但是Kiddo类没有做到这一点。



Answer 3:

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();
    }
}


Answer 4:

最后我要起一个解决问题的替代解决方案。

  • 我创建的扩展爷爷的中间类。
  • 然后,两个爸爸和老兄扩展该类。
  • 老兄需要爸爸的一些中间的功能,但不喜欢它的构造函数,因此类有附加功能和两个扩展。

我已经upvoted其他两个答案,对于一个丑陋的问题提供了有效的又难看的解决方案:)



Answer 5:

不使用标志,并在您的情况可能工作的另一种选择:

<?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";


Answer 6:

用美丽解决方案Reflection

<?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();


Answer 7:

我同意“太多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;

我得到的结果如预期:

老兄

爷爷

这是一个功能不是bug,请在此供大家参考:

https://bugs.php.net/bug.php?id=42016

这只是它的工作方式。 如果它认为它是从正确的上下文来此通话版,但不强制静态调用。

相反,它只会保留$这一点,并感到高兴。

父::()方法以相同的方式工作,你不必将方法定义静态的,而是它可以在同一范围内调用。 尝试了这一点更有趣:

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;

严格的标准:非静态方法老兄::你好()不应该被静态调用,在不兼容的情况下假设$此

您可以使用instanceof来确定是否可以调用一个孩子::()方法在父类的方法:

if ($this instanceof Kiddo) Kiddo::hello();


Answer 8:

有这一个简单的解决方案,但它要求你确切地知道有多少继承当前类已经走过了。 幸运的是,的了get_parent_class()参数允许类数组成员是类的字符串名字以及一个实例本身。

请记住,这也内在地依赖于调用类的__construct()方法的静态,但一个继承的实例化范围内的对象在这种特殊情况下的差异可以忽略不计(啊,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()的限制的情况下可行的解决方案,但在控制的情况下,按预期工作。



Answer 9:

你可以叫爷爷:: __从你想去的地方和$ this关键字将引用到当前类的实例构造。 但要注意使用这个方法,你不能从这个其它上下文访问受保护的属性和当前实例的方法,只有公共元素。 =>所有工作和officialy支持 。

// 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();


Answer 10:

关于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 

因此,一个扩展类(子)内,您可以使用

parent::paFkt(); 

要么

Pa::paFkt();

访问父(或爷爷的)(不是私人)功能。

课外高清

$test::paFkt();

将特罗严格错误(非静态函数)。



Answer 11:

好吧,还有一个丑陋的解决方案:

创建爸爸像一个函数:

protected function call2Granpa() {
     return parent::__construct();
}

然后在老兄,你使用:

parent::call2Granpa(); //代替爸爸调用构造函数。

我认为它可以工作...我还没有测试它,所以我不知道,如果是正确创建的对象。

我用这个方法,但与非构造函数。



Answer 12:

<?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的构造内做任何事情。 中运行,将输出:

嘿,我是大霸嘿我是个孩子



Answer 13:

// 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”。



Answer 14:

    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();
    }
}


Answer 15:

从PHP 7 u可以使用

parent::parent::__construct();



文章来源: How do I get a PHP class constructor to call its parent's parent's constructor