我需要在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
    }
}

我知道这是一件很奇怪的事情,我正试图找到一种不难闻的方法,但尽管如此,我很好奇这是否可能。


当前回答

你必须使用外公::__construct(),没有其他的快捷方式。此外,这也破坏了Papa类的封装——当读取或处理Papa时,应该可以安全地假设__construct()方法将在构造过程中被调用,但Kiddo类不会这样做。

其他回答

对此有一个更简单的解决方案,但它要求您确切地知道当前类已经经历了多少继承。幸运的是,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()的限制,对于不知道发生了多少继承的情况,这不是一个可行的解决方案,但在受控的情况下,它可以按预期工作。

你可以从你想要的地方调用Grandpa::__construct, $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();
<?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的构造中做任何事情。运行该命令将输出:

嘿,我是爷爷 嘿,我是个孩子

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

在Papa中创建一个函数:

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

然后在Kiddo中使用:

父:call2Granpa ();//而不是调用Papa中的构造函数。

我认为这可行……我还没有测试过,所以我不确定是否 对象被正确创建。

我使用了这种方法,但是使用了非构造函数。

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