gpt4 book ai didi

php - "Overloading"PHP 中的私有(private)方法

转载 作者:可可西里 更新时间:2023-11-01 12:18:30 26 4
gpt4 key购买 nike

我知道我不能在 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 严格标准:Child::foo() 声明应与/var/www/boludo.php 第 17 行中的 Base::foo($arg) 兼容

我假设 foo($arg) 方法在 Child 类中是不可见的,因为它是 private。所以,我没有重载 foo,我只是创建了一个名为 foo 的方法。

最佳答案

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

public function foo($arg = null) {

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

PHP 中的可见性完全与运行时访问有关。它不会影响您如何扩展/组合/重载类和方法。从子类型中的父类(super class)型中放松私有(private)方法的可见性将在子类型中添加一个单独的方法,而无法访问父类(super class)型中的相同命名方法。但是,PHP 将为这些假设一个父子关系。但这并没有引起通知。至少,不是靠它自己。

您收到通知的原因是您还试图更改方法签名。您的 foo() 不再需要将 $arg 传递给它。当您假定方法之间存在父子关系时,这是一个问题,因为 Liskov Substitution Principle声明“如果 S 是 T 的子类型,则类型 T 的对象可以替换为类型 S 的对象” 而不会破坏程序。换句话说:如果您有使用 Base 的代码,您应该能够将 Base 替换为 Child 并且该程序仍然可以正常工作它正在使用 Base

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

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

现在想象 Child 更改 bar() 以需要一个参数。如果您随后将 BaseChild 传递给客户端,您将破坏客户端,因为客户端调用 $base->bar();没有争论。

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

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

请注意,LSP 也适用于方法可能返回的内容。 PHP 只是不在签名中包含返回类型,所以您自己已经考虑到了这一点。您的方法必须返回父类(super class)型返回的内容或行为等效的内容。

关于php - "Overloading"PHP 中的私有(private)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18288774/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com