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

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


当前回答

<?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中的构造函数。

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

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

丑陋的解决方法是将一个布尔参数传递给Papa,表明您不希望解析它的构造函数中包含的代码。即:

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

使用反射的美丽解决方案。

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

我最终想出了一个解决问题的替代方案。

我创建了一个中间类,扩展了爷爷。 然后爸爸和孩子都延长了这个课程。 Kiddo需要Papa的一些中间功能,但不喜欢它的构造函数,所以类有额外的功能,并扩展了它。

我对另外两个答案大加赞赏,它们为一个更丑陋的问题提供了有效但丑陋的解决方案:)

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