如何在php中调用受保护的方法


How to call a protected method in php?

下面是类的结构。我希望Observer:callme()也可以从Children调用。

class Observer
{
    protected callme()
    {
    }
}
class Parent extends Observer
{
    function createChild()
    {
        $this->callme(); // this is OK
        return new Child ($this);
    }
}
class Child
{
    private $this myParent;
    public function __constructor ($myParent)
    {
        $this->myParent = $myParent;
    }
    public function __destroy()
    {
        $this->myParent->callme(); // FAIL!
    }
}

那么如何使FAIL工作呢?(不公开,因为它只在"Parent"answers"Children"内部使用)

问题是受保护的方法只能从同一个类或类的子类访问。你能做的就是从Parent继承Child类,像这样:

class Child extends Parent
{
    public function __constructor ()
    {
        parent::__constructor();
    }
    public function __destroy()
    {
        $this->callme(); // Should work!
    }
}

或者将方法更改为public。

顺便说一句,这段代码是你将要使用的某种真正的代码吗?接收父对象的构造函数似乎是错误的。你想要完成什么?

protected意味着您只能从同一个类和子类中调用该方法。你想做的事是不可能的。如果可以从任何地方调用这些方法,那么protected关键字就没有意义了。

在c++中有friend关键字来实现你想要的:你可以将Child定义为Observer的friend(这必须从Observer中完成),然后你可以从Child的方法中调用Observer中的所有方法(包括private和protected)。但是PHP中不存在这样的关键字

我对你问题的评论解释了为什么它不起作用。根据您的澄清,MyChild不应该扩展MyParent,这个答案显示了一种完成您所问问题的方法。

这是一个hack的例子,它利用了一个事实,即php不关心你是否在你自己以外的其他实例上调用受保护的方法,只要你共享受保护方法的祖先。

我不得不改变一些代码,使其有效的php。__constructor不是php构造函数的名字

hacky.php

<?php
class Observer
{
    protected function callme()
    {
        echo 'I was called from ' . get_called_class(), PHP_EOL;
    }
}
class MyParent extends Observer
{
    public function createMyChild()
    {
        $this->callme(); // this is OK
        return new MyChild ($this);
    }
}
class MyChild extends Observer // hackey extends
{
    private $myMyParent;
    public function __construct($myMyParent)
    {
        $this->myMyParent = $myMyParent;
        $this->myMyParent->callme();
    }
}
$p = new MyParent;
$c = $p->createMyChild();
结果:

$ php hacky.php
I was called from MyParent
I was called from MyParent

我想我找到解决办法了:

class Parent extends Observer
{
    function createChild()
    {
        $this->callme(); // this is OK
        return new Child (function() { $this->callme(); });
    }
}
class Child
{
    private $gatewayFunction;
    public function __constructor (Closure $gatewayFunction)
    {
        $this->gatewayFunction = $gatewayFunction;
    }
    public function __destroy()
    {
        $this->gatewayFunction->__invoke();
    }
}

谁要拉屎?:)