覆盖类常量与属性


99

我想更好地理解为什么在以下情况下,类常量与实例变量的继承方式有所不同。

<?php
class ParentClass {
    const TEST = "ONE";
    protected $test = "ONE";

    public function showTest(){
        echo self::TEST;
        echo $this->test;
    }
}

class ChildClass extends ParentClass {
    const TEST = "TWO";
    protected $test = "TWO";

    public function myTest(){
        echo self::TEST;
        echo $this->test;
    }
}

$child = new ChildClass();
$child->myTest();
$child->showTest();

输出:

TWO
TWO
ONE
TWO

在上面的代码中,ChildClass没有showTest()方法,因此ParentClass showTest()方法由继承使用。结果表明,由于该方法是在ParentClass上执行的,因此将评估TEST常量的ParentClass版本,而由于它是通过继承在ChildClass上下文中进行评估的,因此将对ChildClass成员变量$ test进行评估。

我已经阅读了文档,但似乎看不到任何细微差别。谁能给我一些启示?


WTF?不断压倒!!不要这样做!决不!
qwert_ukg '16

2
@qwert_ukg确实。有人应该将其传达给PHP开发人员。或者至少允许final...
卢克Sawczak

1
即使对于持续覆盖,也肯定有足够好的用例:]
Arziel

Answers:


194

self::不了解继承,并且始终引用其正在执行的类。如果您使用的是php5.3 +,则可以尝试static::TESTstatic::继承一样。

区别在于static::使用“后期静态绑定”。在此处查找更多信息:

http://php.net/manual/en/language.oop5.late-static-bindings.php

这是我编写的简单测试脚本:

<?php

class One
{
    const TEST = "test1";

    function test() { echo static::TEST; }
}
class Two extends One
{
    const TEST = "test2";
}

$c = new Two();

$c->test();

输出

test2

22
+提及static::
杰森·麦克雷里

太棒了 感谢您的澄清,并提供了有关后期静态绑定的其他信息(我尚未摘要)。
Tom Auger 2012年

3
由于test()不是静态方法,为什么不$this::TEST与PHP5.3 +一起使用?
Xenos

@Xenos,您好-示例的目的是表明在类One中执行的实例级代码正在从类Two中检索静态值。self :: TEST将返回“ test1”,其中static :: TEST返回预期的“ test2”-希望能有所帮助,感谢您的答复!
David Farrell 2014年

嗨,@ DavidFarrell-是的,我得到了self::/的static::区别,但我不知道为什么使用static::代替$this::(not self::)。有没有之间的差异$this::static::(因为有一间static::/ $this::self::)?
Xenos 2014年

17

在PHP中,self是指在其中定义被调用方法或属性的类。所以你的情况你打电话selfChildClass,所以它使用从该类变量。然后使用selfin ParentClass,因此它将引用该类中的变量。

如果仍然希望子类重写const父类的,则将父类中的以下代码调整为:

public function showTest(){
    echo static::TEST;
    echo $this->test;
}

注意static关键字。这是使用“后期静态绑定”。现在您是父类,将调用子类的const。


亲 静::抽象的,而不是自我::做的工作
BłażejKrzakala
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.