Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/237.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何让PHP类构造函数调用其父类';s的父母';谁的构造函数?_Php_Class_Oop_Inheritance_Constructor - Fatal编程技术网

如何让PHP类构造函数调用其父类';s的父母';谁的构造函数?

如何让PHP类构造函数调用其父类';s的父母';谁的构造函数?,php,class,oop,inheritance,constructor,Php,Class,Oop,Inheritance,Constructor,我需要让PHP中的类构造函数调用其父类的父类的(祖父母?)构造函数,而不调用父类构造函数 // main class that everything inherits class Grandpa { public function __construct() { } } class Papa extends Grandpa { public function __construct() { // call Grandpa's con

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

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

你必须使用
爷爷::\u construct()
,没有其他捷径可走。此外,这会破坏
Papa
类的封装-在读取或处理
Papa
时,可以安全地假设在构造过程中将调用
\u construct()
方法,但是Kiddo类不能做到这一点。

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

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

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

  • 我创建了一个中间类,扩展了爷爷
  • 然后爸爸和基多都扩展了这门课
  • Kiddo需要Papa的一些中间功能,但不喜欢它的构造函数,因此该类具有该附加功能,并对其进行了扩展

我对另外两个答案进行了投票,这两个答案为一个更丑陋的问题提供了有效但丑陋的解决方案:)

好的,另一个丑陋的解决方案:

在Papa中创建一个函数,如:

protected function call2Granpa() {
     return parent::__construct();
}
那么在Kiddo中,你会使用:

parent::call2Granpa()//而不是在Papa中调用构造函数

我认为它可以工作。。。我还没有测试过,所以我不确定 正确创建对象


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

有一个更简单的解决方案,但它要求您确切地知道当前类经历了多少继承。幸运的是,get_parent_class()的参数允许类数组成员作为字符串和实例本身作为类名

请记住,这本身也依赖于静态调用类“\uu 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()的限制,对于您不知道发生了多少继承的情况,这不是一个可行的解决方案,但在受控环境中,它可以按预期工作。

您可以从需要的位置调用grandge::\u构造,$this关键字将引用您当前的类实例。但请小心使用此方法,您无法从其他上下文访问当前实例的受保护属性和方法,只能访问公共元素。=>所有的工作和工作

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

// 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();
请注意,“\uuuuuu构造”并不是什么神奇的名字,您可以称之为“doGrandpaStuff”。

我同意“太多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;
严格标准:不应静态调用非静态方法Kiddo::hello(),假设$this来自不兼容的上下文

您可以使用instanceof确定是否可以在父方法中调用Children::method():

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

当然,这要求您不需要在pa_pa的构造中执行任何操作。运行此命令将输出:

嘿,我是大爸
嘿,我是一个孩子

使用
反射的美丽解决方案

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

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

访问父(或祖父)(非私有)函数

舱外def

$test::paFkt();
将trow严格错误(非静态函数)。

从PHP7U可以使用

parent::paFkt(); 

parent::parent::_construct()

有什么原因不能在Kiddo的构造中实例化爷爷吗?Grampa构造函数为自己设置由其子代继承的属性。爸爸在它的构造器里做了一些事情,会把Kiddo搞砸的。所以我需要在构造过程中调用爷爷构造函数来设置Kiddo的属性。那么Kiddo不应该从爷爷而不是爸爸那里扩展。@MitMaro。我同意这一点,我通过创建一个中间类来扩展我的祖父,从而解决了我的实际问题。然后爸爸和基多都扩展了这门课。Kiddo需要Papa的一些中间功能,但不喜欢它的构造函数,所以这个类有额外的功能,并且都扩展了它。这是一个完美的解决方案。你应该把它作为答案贴出来。我不明白怎么贴。将_构造声明为静态会导致我在PHP5.3下出现以下错误“致命错误:构造函数外公::_构造()不能是静态的”。尝试时,我没有将其声明为静态的。我正常地创建了类结构,但没有调用parent::_construct(),而是调用了grandon::_construct(),它成功了。我看起来也不对,但整个问题有点奇怪。同意。我一直在使用它——你可以通过它的名字来调用一个类,而不仅仅是通过
父类
自我
的神奇名字。大家都知道我深造了三四节课。事实上,我已经开始用我的基类的名称来引用它,而不是用parent,这样我确信我总是得到了正确的对象。EvilChookie的solusion是最好的。应该是认可的答案。比你挑剔@如果您使用的是PHP5.3.0或更高版本,SparK很可能会解决您的用例。我认为更好的方法是将您试图使用的功能从构造的方法中分离出来,并转换为受保护的方法。然后你可以从构造器中有选择地调用这个方法。这并没有回答你刚才提到的问题。如果现实世界弄乱了一些本应清晰和有限的东西,就会发生这种情况。这个问题很遗憾。就我个人而言,我不会选择这样做
<?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();
    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();
    }
}
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();