Переопределение констант класса и свойств


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 (), поэтому метод showTest () ParentClass используется по наследству. Результаты показывают, что, поскольку метод выполняется в ParentClass, оценивается версия ParentClass константы TEST, тогда как, поскольку она оценивается в контексте ChildClass через наследование, оценивается переменная-член ChildClass $ test.

Я прочитал документацию, но, похоже, не вижу упоминания об этом нюансе. Может ли кто-нибудь пролить свет на меня?


Какого черта? Постоянное преобладание !? Не делай этого! никогда!
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::.
Джейсон МакКрири

Потрясающие. Спасибо за разъяснения и за дополнительную информацию о поздних статических привязках (которые мне еще предстоит переварить).
Tom Auger

3
Поскольку test()это не статический метод, почему бы не использовать его $this::TESTс PHP5.3 +?
Xenos

Привет, @Xenos - Целью примера было показать, что код уровня экземпляра, выполняемый в классе One, извлекает статические значения из класса 2. self :: TEST вернул бы "test1", где static :: TEST вернул бы ожидаемое "test2" - Надеюсь, что это поможет, спасибо за ответ!
Дэвид Фаррелл

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

17

В PHP self относится к классу, в котором определен вызываемый метод или свойство. Так что в вашем случае вы звоните selfв ChildClass, поэтому он использует переменную из этого класса. Затем вы используете selfin 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.