“重载"是指PHP中的私有方法 [英] "Overloading" a private method in PHP

查看:55
本文介绍了“重载"是指PHP中的私有方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道我无法重载PHP中的方法.而且,据我所知,扩展基类的类看不到类中的private方法.那么为什么这不起作用?

I know I cannot overload methods in PHP. And, as far as I know, private methods in a class are invisible to classes that extend the base class. So why this does not work?

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的方法.

I assumed that foo($arg) method is invisible in Child class because is private. So, I'm not overloading foo, I'm just creating a method called foo.

推荐答案

要修复该通知,只需将Child中的foo()更改为

To fix the Notice, simply change foo() in the Child to

public function foo($arg = null) {

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

As to the question "why does this not work":

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

Visibility in PHP is strictly about runtime access. It doesn't affect how you can extend/compose/overload classes and methods. Loosening the visibility of a private method from a Supertype in a Subtype will add a separate method in the subtype with no access to the same named method in the supertype. However, PHP will assume a parent-child relationship for these. That didn't cause the Notice though. At least, not on it's own.

之所以收到通知,是因为您随后还要尝试更改方法签名.您的foo()不再需要将$arg传递给它.当您假设方法之间存在父子关系时,这是一个问题,因为 Liskov替代原理指出如果S是T的子类型,则可以用类型S的对象替换类型T的对象" ,而不会破坏程序.换句话说:如果您有使用Base的代码,则应该可以将Base替换为Child,并且该程序应仍可以像使用Base一样工作.

The reason why you get the Notice, is that you are then also trying to change the method signature. Your foo() does no longer require $arg to be passed to it. When you assume a parent-child relationship between the methods, this is a problem because the Liskov Substitution Principle states that "if S is a subtype of T, then objects of type T may be replaced with objects of type S" without breaking the program. In other words: if you have code that uses Base, you should be able to replace Base with Child and the program should still work as if it was using Base.

假设您的Base也具有公共方法bar().

Assume your Base also has a public method bar().

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

现在想象Childbar()更改为需要一个参数.如果随后将BaseChild传递给客户端,则会断开客户端的连接,因为客户端会在不带参数的情况下调用$base->bar();.

Now imagine Child changes bar() to require an argument. If you then pass Child for Base into the client, you will break the client, because the client calls $base->bar(); without an argument.

很显然,您可以更改客户端以传递参数,但是代码实际上取决于Child定义方法的方式,因此Typehint是错误的.实际上,Child不是Base,因为它的行为不像Base.那是破碎的继承.

Obviously, you could change the client to pass an argument, but then the code really depends on how Child defined the method, so the Typehint is wrong. In fact, Child is not a Base then, because it doesn't behave like a Base. It's broken inheritance then.

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

Now the funny thing is, if you remove that $arg from foo(), you are technically not violating LSP, because the client would still work. The Notice is wrong here. Calling $base->foo(42) in a client that previously used Base will still work with a Child because the Child can simply ignore the argument. But PHP wants you to make the argument optional then.

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

Note that LSP also applies to what a method may return. PHP just doesn't include the return type in the signature, so you have take that into account yourself. Your methods have to return what the Supertype returned or something that is behaviorally equivalent.

这篇关于“重载"是指PHP中的私有方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆