Zastępowanie stałych klas a właściwości


99

Chciałbym lepiej zrozumieć, dlaczego w poniższym scenariuszu istnieje różnica w sposobie dziedziczenia stałych klas w porównaniu ze zmiennymi instancji.

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

Wynik:

TWO
TWO
ONE
TWO

W powyższym kodzie ChildClass nie ma metody showTest (), więc metoda ParentClass showTest () jest używana przez dziedziczenie. Wyniki pokazują, że ponieważ metoda jest wykonywana na ParentClass, oceniana jest wersja ParentClass stałej TEST, natomiast ponieważ jest ona oceniana w kontekście ChildClass poprzez dziedziczenie, oceniana jest zmienna składowa ChildClass $ test.

Przeczytałem dokumentację, ale nie widzę żadnej wzmianki o tym niuansie. Czy ktoś może rzucić dla mnie trochę światła?


WTF? Ciągłe zastępowanie !? Nie rób tego! nigdy!
qwert_ukg

2
@qwert_ukg Rzeczywiście. Ktoś powinien to przekazać twórcom PHP. Albo przynajmniej pozwól final...
Luke Sawczak

1
Z pewnością są wystarczająco dobre przypadki użycia nawet do ciągłego
zastępowania

Odpowiedzi:


194

self::Nie jest świadomy dziedziczenia i zawsze odwołuje się do klasy, w której jest wykonywany. Jeśli używasz php5.3 +, możesz spróbować static::TESTtak, jak static::jest to uwzględniające dziedziczenie.

Różnica polega na tym, że static::używa się „późnego wiązania statycznego”. Więcej informacji znajdziesz tutaj:

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

Oto prosty skrypt testowy, który napisałem:

<?php

class One
{
    const TEST = "test1";

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

$c = new Two();

$c->test();

wynik

test2

22
+ za wspomnienie static::.
Jason McCreary

Niesamowite. Dziękuję za wyjaśnienie i dodatkowe informacje na temat późnych wiązań statycznych (których jeszcze nie przetrawiłem).
Tom Auger

3
Ponieważ test()nie jest to metoda statyczna, dlaczego nie używać $this::TESTz PHP5.3 +?
Xenos

Cześć @Xenos - Celem przykładu było pokazanie, że kod na poziomie instancji wykonywany w klasie pierwszej pobierał wartości statyczne z klasy drugiej. self :: TEST zwróciłby „test1”, gdzie static :: TEST zwraca oczekiwany „test2” - Mam nadzieję, że to pomoże, dzięki za odpowiedź!
David Farrell

Cześć @DavidFarrell - Tak, dostałem różnicę self::/, static::ale nie rozumiem, dlaczego używam static::zamiast $this::(nie self::). Czy istnieje różnica między $this::istatic:: (ponieważ jest jeden między static::/ $this::a self::)?
Xenos

17

W PHP self oznacza klasę, w której zdefiniowana jest wywoływana metoda lub właściwość. Tak w przypadku, gdy dzwonisz selfw ChildClass, więc używa zmiennej z tej klasy. Następnie używasz selfin ParentClass, więc będzie odwoływać się do zmiennej w tej klasie.

jeśli nadal chcesz, aby klasa podrzędna zastępowała constklasę nadrzędną, dostosuj następujący kod w klasie nadrzędnej do tego:

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

Zwróć uwagę na staticsłowo kluczowe. To jest używane „późne wiązanie statyczne”. Twoja klasa nadrzędna będzie teraz wywoływać const klasy podrzędnej.


zawodowiec. static :: wykonał pracę w abstrakcji zamiast siebie ::
Błażej Krzakala
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.