“重载” PHP中的私有方法

恩里克·马科斯(Enrique Marcos)

我知道我无法在PHP中重载方法。而且,据我所知,private扩展基类的类看不到类中的方法。那么为什么这行不通呢?

class Base {
  private function foo($arg) {
     print "Base $arg";
  }
}

class Child extends Base {
  public function foo() {
     print "Child";
  }
}

$c = new Child;
print $c->foo();

错误:

PHP Strict Standards: Declaration of Child::foo() should be compatible with Base::foo($arg) in /var/www/boludo.php on line 17

我认为foo($arg)方法在Child类中是不可见的,因为是private因此,我没有超载foo,我只是创建了一个名为的方法foo

高登

要修正此通知,只需将foo()“子项”更改

public function foo($arg = null) {

关于“为什么这不起作用”的问题:

PHP中的可见性完全是关于运行时访问的。它不会影响您如何扩展/组成/重载类和方法。从子类型的父类型中松开私有方法的可见性将在子类型中添加单独的方法,而无法访问父类型中的相同命名方法。但是,PHP将为此假定一个父子关系。但这并没有引起通知。至少不是一个人。

之所以收到通知,是因为您随后还试图更改方法签名。foo()不再需要$arg将其传递给它。当您假定方法之间的父子关系时,这是一个问题,因为《里斯科夫替代原理》指出:“如果S是T的子类型,则T类型的对象可以用S类型的对象替换”而不会破坏程序。换句话说:如果您有使用的代码,则Base应该可以将其替换BaseChild并且该程序应仍像使用一样正常工作Base

假设您Base也有一个公共方法bar()

class SomeClientUsingBase
{
    public function doSomethingWithBase(Base $base)
    {
        $result = $base->bar();
        // …

现在想象需要参数的Child更改bar()如果随后将其传递ChildBase客户端,则将断开客户端,因为客户端在调用时$base->bar();不带参数。

显然,您可以更改客户端以传递参数,但是代码实际上取决于Child方法的定义方式,因此Typehint是错误的。实际上,Child不是一个Basethen,因为它的行为不像Base然后,它是残缺的继承。

现在有趣的是,如果$arg从中删除它,foo()技术上讲,您不会违反LSP,因为客户端仍然可以工作。该通知在这里是错误的。调用$base->foo(42)以前使用过的客户端Base仍然可以使用,Child因为Child可以简单地忽略该参数。但是PHP希望您随后将参数设为可选。

请注意,LSP也适用于方法可能返回的内容。PHP只是在签名中不包含返回类型,因此您自己考虑了这一点。您的方法必须返回Supertype返回的内容或行为上等效的内容。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章