Überschreiben von Klassenkonstanten gegenüber Eigenschaften

98

Ich möchte besser verstehen, warum es im folgenden Szenario einen Unterschied in der Art und Weise gibt, wie Klassenkonstanten gegenüber Instanzvariablen vererbt werden.

<?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();

Ausgabe:

TWO
TWO
ONE
TWO

Im obigen Code verfügt ChildClass nicht über eine showTest () -Methode, daher wird die ParentClass showTest () -Methode bei der Vererbung verwendet. Die Ergebnisse zeigen, dass, da die Methode auf der ParentClass ausgeführt wird, die ParentClass-Version der TEST-Konstante ausgewertet wird, während die ChildClass-Mitgliedsvariable $ test ausgewertet wird, da sie im ChildClass-Kontext über die Vererbung ausgewertet wird.

Ich habe die Dokumentation gelesen, kann aber anscheinend keine Erwähnung dieser Nuance sehen. Kann jemand etwas Licht für mich bringen?

Tom Auger
quelle
WTF? Ständiges Überschreiben!? Mach das nicht! noch nie!
qwert_ukg
2
@qwert_ukg In der Tat. Jemand sollte dies den Entwicklern von PHP mitteilen. Oder zumindest erlauben final...
Luke Sawczak
1
Es gibt sicher genug Anwendungsfälle, auch für ständiges Überschreiben:]
Arziel

Antworten:

193

self::Ist nicht vererbungsbewusst und bezieht sich immer auf die Klasse, in der es ausgeführt wird. Wenn Sie php5.3 + verwenden, können Sie versuchen, static::TESTwie vererbungsbewusst static::.

Der Unterschied besteht darin, dass static::"späte statische Bindung" verwendet wird. Weitere Informationen finden Sie hier:

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

Hier ist ein einfaches Testskript, das ich geschrieben habe:

<?php

class One
{
    const TEST = "test1";

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

$c = new Two();

$c->test();

Ausgabe

test2
David Farrell
quelle
22
+ zum Erwähnen static::.
Jason McCreary
Genial. Vielen Dank für die Klarstellung und für die Bereitstellung der zusätzlichen Informationen zu spät statischen Bindungen (die ich noch nicht verdaut habe).
Tom Auger
3
Da test()es sich nicht um eine statische Methode handelt, warum nicht $this::TESTmit PHP5.3 + verwenden?
Xenos
Hi @Xenos - Das Ziel des Beispiels war es zu zeigen, dass Code auf Instanzebene, der in Klasse 1 ausgeführt wird, statische Werte aus Klasse 2 abruft. self :: TEST hätte "test1" zurückgegeben, wobei static :: TEST den erwarteten "test2" zurückgibt - Ich hoffe, das hilft, danke für die Antwort!
David Farrell
Hi @DavidFarrell - Ja, ich habe den self::/ static::Unterschied, aber ich verstehe nicht, warum ich static::statt $this::(nicht self::) benutze . Gibt es einen Unterschied zwischen $this::und static::(da es einen zwischen static::/ $this::und gibt self::)?
Xenos
16

In PHP bezieht sich self auf die Klasse, in der die aufgerufene Methode oder Eigenschaft definiert ist. Also in Ihrem Fall Sie anrufen selfin ChildClass, so dass es die Variable aus dieser Klasse verwendet. Dann verwenden Sie selfin ParentClass, sodass es sich dann auf die Variable in dieser Klasse bezieht.

Wenn Sie weiterhin möchten, dass die untergeordnete Klasse constdie übergeordnete Klasse überschreibt , passen Sie den folgenden Code in Ihrer übergeordneten Klasse daran an:

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

Beachten Sie das staticSchlüsselwort. Dies verwendet "späte statische Bindung". Jetzt ruft Ihre Elternklasse die Konstante Ihrer Kinderklasse auf.

w00
quelle
Profi. statisch :: Job in Abstraktion statt Selbst gemacht ::
Błażej Krzakala