Пытаясь понять поздние статические привязки в php

<?php
class Record {

    protected static $tableName = 'base';

    public static function getTableName() {
        echo self::$tableName;
    }
}
class User extends Record {
    protected static $tableName = 'users';
}
User::getTableName(); 

Он показывает: base

Вопрос:

Я знаю, что могу изменить проблему, изменив эту строку echo self::$tableName; на echo static::$tableName;, она называется "поздними статическими привязками", я прочитал документ здесь, но все еще не совсем понял. Не могли бы вы дать мне несколько объяснений:

а. почему эта строка кода echo self::$tableName; показывает: base?

б. почему эта строка кода echo static::$tableName; показывает: пользователи?

Ответ 1

self "привязан" во время компиляции статически. Это означает, что при компиляции кода определяется, к чему относится self. static разрешается во время выполнения, то есть когда код выполняется. Это позднее статическое связывание. И это различие.

С self, это определяется во время компиляции (когда код "читается" ), что self относится к Record. Позже код для User анализируется, но self::$tableName в Record уже ссылается на Record::$tableName и больше не может быть изменен.

Когда вы используете static, ссылка не будет устранена немедленно. Он разрешается только при вызове User::getTableName(), после чего вы находитесь в контексте User, поэтому static::$tableName разрешено User::$tableName.

Другими словами: self всегда относится к классу, в котором он был написан, и не имеет двух способов. То, к чему относится static, зависит от того, какой контекст он использовал; на практике это означает, что он может ссылаться на дочерние классы, если класс, в котором он встречается, расширяется. Это заставляет его работать как $this, только для статических контекстов.

Ответ 2

self ссылается на область определения класса.

static ссылается на область вызовов классов.

self::$tableName ссылается на класс, в котором он был определен. т.е. Запись

static::$tableName ссылается на класс, на который он был вызван. т.е. Пользователь

Ответ 3

Пример ниже даст минимальный пример позднего статического привязки:

class A {
    static public $name = "A";

    static public function getName () {
        return self::$name;
    }

    static public function getNameLateStaticBinding () {
        return static::$name;
    }
}


class B extends A {
    static public $name = "B";
}



// Output: A
echo A::getName(), "\n";

// Output: A
echo B::getName(), "\n";

// Output: B
echo B::getNameLateStaticBinding() , "\n";

B::getName() выводит переменную $name из A, так как self вычисляется из класса абсолютного тока, который вы определили self in. Чтобы решить такие случаи, используйте static.