提问者:小点点

从继承的类调用私有方法


我想用PHP在我的简单ORM中实现一个钩子系统:

class Record {
  public function save() {
    if (method_exists($this,"before_save")) {
      $this->before_save();
    }
    //...Storing record etc.
  }
}

class Payment extends Record {
  private function before_save() {
    $this->payed_at = time();
  }
}

$payment = new Payment();
$payment->save();

这会导致一个致命错误:

致命错误:调用私人方法付款::before_save()从上下文'记录'中

有道理。

我可以将范围更改为public,但这似乎很难看:在保存()之前,除了支付之外,没有人与有任何关系。最好不要公开,伊姆霍。

如何使记录调用成为从记录继承的类上的私有方法?


共3个答案

匿名用户

在将save函数添加到记录类之前,将其可访问设置为protected。现在,所有从Record继承的类都将具有这个函数,如果它们不覆盖它,它将不会起任何作用。如果他们覆盖它,它可以实现所需的功能。

class Record {
  public function save() {
    $this->before_save();
    //...Storing record etc.
  }

  protected function before_save() {
     return;
  }
}

class Payment extends Record {
  protected function before_save() {
    $this->payed_at = time();
  }
}

匿名用户

获胜的答案不能回答问题。有关“公共”、“受保护”、“私人”和“最终”的信息应可在任何博客或书籍上获得。

这个问题询问如何使用继承类中的“private”函数。这里的用例是,您被迫使用设计糟糕的第三方代码,不分青红皂白地使用私有函数,并且面临着要么找到使用私有函数的方法,要么放弃整个回购协议。

这是问题的答案。

class foo {

    protected $text = "foo";

    private function bar($text)
    {
        return $text.'->'.$this->text;
    }
}

class fooChild extends foo{

    protected $text = "bar";

    public function barChild()
    {
        $r = new \ReflectionMethod(parent::class, 'bar');
        $r->setAccessible(true);
        //return $r->invokeArgs(new foo(), ['output']); // output->foo
        return $r->invokeArgs($this, ['output']);//output->bar
    }
}

echo (new fooChild())->barChild();

使用反射方法类,您可以从继承类调用私有方法。您可以看到使用$this和父级的新实例的区别。不会从新实例的子实例中设置属性。

匿名用户

检查错误消息

Call to private method Payment::before_save() from context 'Record'

这意味着您正试图在记录中调用支付中定义的函数。类Record没有before\u save方法,因为它在继承链中的位置比定义函数的位置更高。

换句话说,由于父子关系是记录(是付款的父项)付款可以访问记录函数(通过从父项继承),但反之亦然(父项不能“继承”子类函数)。您可以使您的函数受到保护,这将使它能够在继承链上下访问,但您可能需要重新考虑体系结构,并决定是否需要这样做。。理想情况下,您应该在记录中定义该函数,并在支付中覆盖该函数

另外(我可能有错),但通常不需要显式检查方法\u是否存在,除非您正在创建一个运行时类可以重叠和/或生成的真正动态系统。如果您从头定义一个基于类的系统,并且您知道如何缝合各个部分,通常您不需要在运行时检查方法\u是否存在。。。只是一个想法。。