fn(); ?> 通过运行它,您将得到以下输出: Context: Class:A Parent: Context: Class:C P-6ren">
gpt4 book ai didi

PHP:在继承链的每个对象的上下文中调用方法

转载 作者:行者123 更新时间:2023-12-04 16:19:49 27 4
gpt4 key购买 nike

看下面的代码片段:

<?php

class A {
function fn() {
print 'Context: Class:' . get_class($this)
. ' Parent:' . get_parent_class($this) . "\n";
if(get_parent_class($this)) {
parent::fn();
}
}
}

class B extends A { }
class C extends B { }

$a = new A();
$c = new C();

$a->fn();

print "\n";

$c->fn();

?>

通过运行它,您将得到以下输出:

Context: Class:A Parent:

Context: Class:C Parent:B

Fatal error: Cannot access parent:: when current class scope has no parent in /home/andrei/test/test.php on line 10

我认为应该是这样的:

Context: Class:A Parent:

Context: Class:C Parent:B
Context: Class:B Parent:A
Context: Class:A Parent:

你觉得怎么样?如果 get_parent_class($this) 返回一个非 false 值,我们是否应该安全地假设 Parent::已定义? fn() 在什么类上下文中调用?

最佳答案

使用parent::或self::的调用被认为是静态的。这些应该在定义类的上下文中进行评估,而不是在调用对象的范围内。 PHP 5.3 为单词 static 添加了新的含义,可用于静态调用例如父级和 self,但将在调用类的上下文中进行评估。这称为后期静态绑定(bind)。此页面上的更多信息:

http://www.php.net/lsb

编辑:

经过一番思考,我相信这种行为是完全可以接受的。首先,让我们看看为什么 A 希望其 foo() 方法调用其父级的 foo() 方法,因为 A 没有父级。因为,它希望该方法始终被执行,而不 pipe 级的实现如何。如果是这样,还有其他解决方案,但不是那么好:

class A
{
final public function __construct()
{
echo __METHOD__;

$this->foo();

$init = array($this, 'init');
$args = func_get_args();

call_user_func_array($init, $args);
}

// init would be used as a pseudo-constructor in children
public function init()
{}

final private function foo()
{
echo __METHOD__;
}
}

class B extends A
{}

class C extends B
{}

$c = new C;

如果您尝试执行的是链中的每个 foo() 方法,那么这是预期的行为。如果有一个 B::foo() 函数,那么它就会被执行,如果它包含对 Parent::foo() 的调用,那么 A::foo() 也会被执行。

所以,parent::foo() 可能有点令人困惑。它应该读成这样(抱歉,但我找不到更好的例子):

the_first_parent_in_the_inheritance_chain_which_has_a_foo_method::foo()

这就是您真正感兴趣的。为什么您要在 B 的上下文中调用 foo() ?我能想到的唯一原因是为了从 B 访问私有(private)成员。但是,A 如何知道 B 有什么私有(private)成员呢?不可以。您不能在 A::foo() 中使用 A 未声明的成员。除非A是抽象的,定义了一些抽象方法。当然,A 可以将该属性声明为私有(private)(B 不能为被重写的成员提供比父级成员更低的可见性,我们的目标是 B 应该拥有一个私有(private)的)。然后 B 覆盖该属性,将其设为我们想要的私有(private)属性。现在,如果您的代码可以工作,A 或 C 将可以访问 B 的私有(private)成员,尽管它不应该。这违反了规则。

是否存在任何情况下您想要您所询问的行为?

关于PHP:在继承链的每个对象的上下文中调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/782033/

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