我想用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,但这似乎很难看:在保存()之前,除了支付之外,没有人与有任何关系。最好不要公开,伊姆霍。
如何使记录调用成为从记录继承的类上的私有方法?
在将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是否存在
。。。只是一个想法。。