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

3

这是类的结构。我希望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”和其“Children”内部使用)

2
为什么要保护它,如果你想公开访问它?直接将其公开,就像应该的那样。 - John Conde
2
除非你扩展父级,否则它不是子级。 - John Conde
1
在你的例子中,Child 不属于与 ObserverParent 相同的类层级,因此它无法调用 Observer::callme()。你的类名表明你希望 Parent 成为 Child 的超类,但代码并非如此。 - Josh J
3
Parent中实例化一个新的Child对象并不会使得Child成为Observer的子类,因此受保护的方法callme()在其中不可用。 - BenM
1
你可能想看看这个:https://dev59.com/VG855IYBdhLWcg3waDeR?rq=1 和这个:https://dev59.com/HnRC5IYBdhLWcg3wD87r?rq=1 - GiamPy
显示剩余2条评论
4个回答

3
问题在于受保护的方法只能从同一类或其子类中访问。您可以这样做:将 Child 类从 Parent 扩展,像这样:

class Child extends Parent
{
    public function __constructor ()
    {
        parent::__constructor();
    }

    public function __destroy()
    {
        $this->callme(); // Should work!
    }
}

或者将方法更改为public。

顺便问一下,这段代码是你要使用的真实代码吗?那个接收父对象的构造函数似乎是错误的。你想要实现什么目标?


是的,那没问题,但这种架构不是那样的。只能有一个“父”和许多“子”。 “子”并不真正是“子”,而是一个包含的对象。 - John Smith
1
为什么不分享你的真实代码或者至少更好地说明你想做什么,这里有很多有经验的开发人员可以帮助你设计架构,包括我自己 :D - Yam Frich

2

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

在C++中,有friend关键字可以实现你想要的功能:你可以将Child定义为Observer的friend(必须在Observer内部完成),然后你可以在Child的方法中调用Observer中的所有方法(包括私有和受保护的方法)。但是,在PHP中不存在这样的关键字。


是的,我听说过这个朋友。 - John Smith

1

我的评论解释了为什么它不起作用。这个答案展示了一种基于你的澄清,即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();

Result:

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

0

我想我找到了解决方案:

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

谁要拉裤子? :)


这不是玩笑,而是真正的解决方案。它非常“脏”,但也很好。 - John Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接