Перевищення констант класу проти властивостей


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, версія ParentClass константи TEST оцінюється, тоді як, оскільки вона оцінюється в контексті ChildClass шляхом успадкування, оцінюється $ тест $ змінної ChildClass.

Я прочитав документацію, але, здається, не бачу жодної згадки про цей нюанс. Чи може хтось пролити на мене світло?


WTF? Постійне переосмислення! Не роби цього! ніколи!
qwert_ukg

2
@qwert_ukg Дійсно. Хтось повинен повідомити це розробникам PHP. Або, принаймні, дозвольте final...
Лука Савзак

1
Напевно є досить хороші випадки використання навіть для постійного
переосмислення

Відповіді:


194

self::Не успадковує і завжди посилається на клас, у якому він виконується. Якщо ви використовуєте php5.3 +, ви можете спробувати, static::TESTяк static::це успадковує.

Різниця полягає в тому, що 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::.
Джейсон МакКрірі

Дивовижно. Дякую за роз’яснення та за надану додаткову інформацію про запізнілі статичні зв’язки (які я ще перетравлював).
Том Ожер

3
Оскільки test()це не статичний метод, чому б не використовувати $this::TESTз PHP5.3 +?
Ксенос

Привіт @Xenos - Метою прикладу було показати, що код рівня екземпляра, який виконується в першому класі, отримує статичні значення з другого класу. self :: TEST повернув би "test1", де статичний :: TEST повертає очікуваний "test2" - Сподіваюся, що це допоможе, дякую за відповідь!
Девід Фаррелл

Привіт @DavidFarrell - Так, я отримав self::/ static::різницю, але я не розумію, чому використовувати static::замість $this::(не self::). Чи є різниця між $this::і static::(оскільки існує одна між static::/ $this::і self::)?
Ксенос

17

У PHP self посилається на клас, у якому визначено викликаний метод або властивість. Так що в вашому випадку ви телефонуєте selfв ChildClass, тому він використовує змінну з цього класу. Потім ви використовуєте selfв ParentClass, тож він буде звертатися до змінної в цьому класі.

якщо ви все ще хочете, щоб дочірній клас переосмислив constбатьківський клас, то відрегулюйте такий код у своєму батьківському класі на це:

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

Зверніть увагу на staticключове слово. Для цього використовується "пізнє статичне зв'язування". Тепер ви, батьківський клас, буде називати const вашого дочірнього класу.


профі. static :: влаштувався на абстракцію замість себе ::
Błażej Krzakala
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.