В чем разница между использованием self
и static
в приведенном ниже примере?
class Foo
{
protected static $bar = 1234;
public static function instance()
{
echo self::$bar;
echo "\n";
echo static::$bar;
}
}
Foo::instance();
производит
1234
1234
Ответы:
Когда вы используете
self
для ссылки на член класса, вы имеете в виду класс, в котором вы используете ключевое слово. В этом случае вашFoo
класс определяет защищенное статическое свойство с именем$bar
. Когда вы используетеself
вFoo
классе для ссылки на свойство, вы ссылаетесь на тот же класс.Поэтому, если вы пытались использовать в
self::$bar
другом месте своегоFoo
класса, но у вас былBar
класс с другим значением свойства, он будет использоватьFoo::$bar
вместоBar::$bar
, что может быть не тем, что вы намереваетесь:Когда вы вызываете метод через
static
, вы вызываете функцию, называемую поздними статическими привязками (введена в PHP 5.3).В приведенном выше сценарии использование
self
приведет кFoo::$bar
(1234). И использованиеstatic
приведет кBar::$bar
(4321), потомуstatic
что интерпретатор принимает во внимание повторное объявление внутриBar
класса во время выполнения.Обычно вы используете поздние статические привязки для методов или даже самого класса, а не свойств, поскольку вы не часто повторно объявляете свойства в подклассах; пример использования
static
ключевого слова для вызова конструктора с поздним связыванием можно найти в этом связанном вопросе: New self vs. new staticОднако это также не исключает использования
static
со свойствами.источник
<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
self::$abc
когда используется внутриclass Foo
, то же самое, что и сказатьFoo::$abc
. Никакое повторное объявление$abc
в подклассе не повлияет на него. AFAIK, единственная причина для использованияself
- это сокращение, чтобы избежать использования имени классаFoo
, которое может быть длиннее. [Это также означает, что вы можете изменить имя класса, не меняя все эти места - но это не основная причина, IMHO.] (Выбор имен PHP неудачен и кажется обратным; «статический» - это тот, который может измениться - который противоположно разговорному значению слова "статический" на естественном языке.)Как уже упоминалось, одно из основных отличий заключается в том, что
static
допускаются поздние статические привязки. Один из наиболее полезных сценариев, который я нашел, был для создания базовых классов для классов Singleton:Использование
return static::$name
в базовом классе вернет то, что было статически прикреплено при расширении. Если бы вы использовалиreturn self::$name
thenB::getName()
, вернули бы пустую строку, поскольку она объявлена в базовом классе.источник
По
self
звонку:Вы можете видеть выше, хотя мы переопределили
$var
нашBar
класс, он все равно возвращается123
, потому что мы явно запросилиself
переменную PHP , которая, в свою очередь,Foo
вместо этого запрашивает переменную s.Теперь, если мы поменяем вызов на
static
, вместо этого мы получимBar
переопределенное значение s:По
static
звонку:источник