【问题标题】:How to call a protected method in php?如何在php中调用受保护的方法?
【发布时间】:2015-12-08 08:43:56
【问题描述】:

这里是类结构。我希望 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 工作? (不公开,因为它只用于“父母”和它的“孩子”)

【问题讨论】:

  • 如果要公开访问,为什么要保护它?只需按应有的方式公开即可。
  • 除非您扩展父级,否则这不是子级。
  • 在您的示例中,ChildObserverParent 不在同一个类层次结构中,因此它不能调用Observer::callme()。您的类名表明您的意思是 ParentChild 的超类,但这不是代码所说的。
  • Parent 内部实例化一个新的Child 对象不会使Child 成为Observer 的子对象,因此受保护的方法callme() 在其中不可用...

标签: php oop


【解决方案1】:

问题是受保护的方法只能从同一个类或类子类中访问。您可以做的是从 Parent 扩展您的 Child 类,如下所示:

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

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

或者只是将方法更改为公开。

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

【讨论】:

  • 是的,没关系,但这个架构不是那样的。只能有一个“父母”和许多“孩子”-ren。 “孩子”并不是真正的“孩子”,而是一个包含的对象
  • 你为什么不分享你的真实代码或者至少更好地了解你想要做什么,这里有很多经验丰富的开发人员可以帮助你解决架构问题,包括我自己 :D跨度>
【解决方案2】:

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

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

【讨论】:

  • 是的,我听说过朋友
【解决方案3】:

我对您的问题的评论解释了为什么它不起作用。此答案显示了一种根据您的说明完成您所要求的方法 MyChild 不应扩展 MyParent

这是一个 hack 示例,它利用了 php 不关心您是否在其他实例上调用受保护方法而不是自己的事实,只要您共享受保护方法的祖先,它就可以工作。

我不得不更改一些代码以使其有效的 php.ini 文件。 __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

【讨论】:

    【解决方案4】:

    我想我找到了解决方案:

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

    谁会自欺欺人? :)

    【讨论】:

    • 这不是开玩笑,它是一个真正的解决方案。它很脏,因为它很好
    猜你喜欢
    • 2016-02-19
    • 2010-11-02
    • 2022-12-28
    • 2013-09-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 2011-05-18
    • 2020-03-31
    相关资源
    最近更新 更多