В PHP 5, в чем разница между использованием self
и $this
?
Когда каждый из них подходит?
В PHP 5, в чем разница между использованием self
и $this
?
Когда каждый из них подходит?
Используйте
$this
для ссылки на текущий объект. Используйтеself
чтобы обратиться к текущему классу. Другими словами, используйте$this->member
для нестатических элементов, используйтеself::$member
для статических элементов.
Вот пример правильного использования $this
и self
для нестатических и статических переменных-членов:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}
new X();
?>
Вот пример неправильного использования $this
и self
для нестатических и статических переменных-членов:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo self::$non_static_member . ' '
. $this->static_member;
}
}
new X();
?>
Вот пример полиморфизма с $this
для функций-членов:
<?php
class X {
function foo() {
echo 'X::foo()';
}
function bar() {
$this->foo();
}
}
class Y extends X {
function foo() {
echo 'Y::foo()';
}
}
$x = new Y();
$x->bar();
?>
Вот пример подавления полиморфного поведения с использованием self
для функций-членов:
<?php
class X {
function foo() {
echo 'X::foo()';
}
function bar() {
self::foo();
}
}
class Y extends X {
function foo() {
echo 'Y::foo()';
}
}
$x = new Y();
$x->bar();
?>
Идея состоит в том, что
$this->foo()
вызывает функцию-членfoo()
любого точного типа текущего объекта. Если объект имеетtype X
, он вызываетX::foo()
. Если объект имеетtype Y
, он вызываетY::foo()
. Но с self :: foo()X::foo()
вызывается всегда.
С http://www.phpbuilder.com/board/showthread.php?t=10354489:
Автор: http://board.phpbuilder.com/member.php?145249-laserlight
Ключевое слово self does NOT относится только к "текущему классу", по крайней мере, не таким образом, что ограничивает вас статическими членами. В контексте нестатического члена self
также предоставляет способ обхода vtable (см. Wiki на vtable) для текущего объекта, Так же, как вы можете использовать parent::methodName()
для вызова родительской версии функции, поэтому вы можете вызвать self::methodName()
для вызова текущей реализации метода.
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getTitle() {
return $this->getName()." the person";
}
public function sayHello() {
echo "Hello, I'm ".$this->getTitle()."<br/>";
}
public function sayGoodbye() {
echo "Goodbye from ".self::getTitle()."<br/>";
}
}
class Geek extends Person {
public function __construct($name) {
parent::__construct($name);
}
public function getTitle() {
return $this->getName()." the geek";
}
}
$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();
Это выведет:
Привет, я Ludwig the geek
До свидания с Людвигом человек
sayHello()
использует указатель $this
, поэтому vtable вызывается для вызова Geek::getTitle()
.
sayGoodbye()
использует self::getTitle()
, поэтому vtable не используется и вызывается Person::getTitle()
. В обоих случаях мы имеем дело с методом объекта-экземпляра и имеем доступ к указателю $this
внутри вызываемых функций.
НЕ ИСПОЛЬЗУЙТЕ self::
, используйте static::
Есть еще один аспект самости, который стоит упомянуть. Досадно, что self::
относится к области действия в точке определения, а не в точке исполнения. Рассмотрим этот простой класс с двумя методами:
class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
Если мы вызовем Person::status()
мы увидим "Человек жив". Теперь рассмотрим, что происходит, когда мы создаем класс, который наследуется от этого:
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
При вызове Deceased::status()
мы ожидаем увидеть "Person is deceased", однако мы видим "Person is alive", поскольку область действия содержит исходное определение метода, когда был определен вызов self::getStatus()
.
PHP 5.3 имеет решение. оператор static::
resolution реализует "позднюю статическую привязку", которая является причудливым способом сказать, что она связана с областью действия вызываемого класса. Измените строку в status()
на static::getStatus()
и вы static::getStatus()
результаты. В более старых версиях PHP вам нужно будет найти ключ для этого.
Смотрите PHP документацию
Так что ответить на вопрос не так, как задали...
$this->
ссылается на текущий объект (экземпляр класса), тогда как static::
ссылается на класс
Чтобы действительно понять, о чем мы говорим, когда говорим о self
versus $this
, нам нужно действительно копаться в том, что происходит на концептуальном и практическом уровне. Я действительно не чувствую, что какие-либо ответы соответствуют этому, поэтому здесь моя попытка.
Пусть начнется разговор о том, что такое класс и объект.
Итак, что есть класс? Многие люди определяют его как план или шаблон для объекта. Фактически, вы можете прочитать больше О классах в PHP здесь. И в какой-то степени это то, чем оно на самом деле. Посмотрим на класс:
class Person {
public $name = 'my name';
public function sayHello() {
echo "Hello";
}
}
Как вы можете сказать, в этом классе есть свойство $name
и метод (функция), называемый sayHello()
.
Очень важно отметить, что класс является статической структурой. Это означает, что класс Person
, однажды определенный, всегда один и тот же, когда вы смотрите на него.
С другой стороны, объект называется экземпляром класса. Это означает, что мы берем "план" этого класса и используем его для создания динамической копии. Эта копия теперь специально привязана к переменной, в которой она хранится. Поэтому любые изменения экземпляра являются локальными для этого экземпляра.
$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"
Мы создаем новые экземпляры класса с помощью оператора new
.
Поэтому мы говорим, что класс является глобальной структурой, а объект является локальной структурой. Не беспокойтесь об этом забавном синтаксисе ->
, мы немного поговорим об этом.
Еще одна вещь, о которой мы должны поговорить, заключается в том, что мы можем проверить, является ли экземпляр instanceof
определенным классом: $bob instanceof Person
, который возвращает логическое значение, если экземпляр $bob
был создан с использованием класса Person
или дочерний элемент Person
.
Итак, позвольте немного разобраться в том, что содержит класс. Существует 5 типов "вещей", которые содержит класс:
Свойства. Подумайте об этом как о переменных, которые будут содержать каждый экземпляр.
class Foo {
public $bar = 1;
}
Статические свойства. Подумайте об этом как о переменных, которые совместно используются на уровне класса. Это означает, что они никогда не копируются каждым экземпляром.
class Foo {
public static $bar = 1;
}
Методы - это функции, которые каждый экземпляр будет содержать (и работать с экземплярами).
class Foo {
public function bar() {}
}
Статические методы. Это функции, которые совместно используются во всем классе. Они работают не, но вместо этого действуют только статические свойства.
class Foo {
public static function bar() {}
}
Константы - Константы разрешенных классов. Не углубляйтесь сюда, но добавляя для полноты:
class Foo {
const BAR = 1;
}
Таким образом, мы сохраняем информацию о контейнере класса и объекта, используя "подсказки" о статике, которые определяют, является ли информация общедоступной (и, следовательно, статической) или нет (и, следовательно, динамической).
Внутри метода экземпляр объекта представлен переменной $this
. Текущее состояние этого объекта есть, и изменение (изменение) любого свойства приведет к изменению этого экземпляра (но не других).
Если метод называется статически, переменная $this
не определена. Это связано с тем, что нет экземпляра, связанного со статическим вызовом.
Интересно, как создаются статические вызовы. Поэтому давайте поговорим о том, как мы получаем доступ к состоянию:
Итак, теперь, когда мы сохранили это состояние, нам нужно получить к нему доступ. Это может немного запутаться (или способ больше, чем бит), поэтому позвольте разделить это на две точки зрения: извне экземпляра/класса (скажем, из обычного вызова функции или из глобальной области ) и внутри экземпляра/класса (из метода в объекте).
С внешней стороны экземпляра/класса наши правила довольно просты и предсказуемы. У нас есть два оператора, и каждый говорит нам немедленно, если мы имеем дело с экземпляром или классом static:
->
- object-operator - это всегда используется, когда мы обращаемся к экземпляру.
$bob = new Person;
echo $bob->name;
Важно отметить, что вызов Person->foo
не имеет смысла (поскольку Person
- это класс, а не экземпляр). Следовательно, это ошибка синтаксического анализа.
::
- scope-resolution-operator - это всегда используется для доступа к статическому свойству или методу класса.
echo Foo::bar()
Кроме того, мы можем вызвать статический метод для объекта таким же образом:
echo $foo::bar()
Очень важно отметить, что, когда мы делаем это извне, экземпляр объекта скрыт от метода bar()
. Это означает, что это точно так же, как работает:
$class = get_class($foo);
$class::bar();
Следовательно, $this
не определяется в статическом вызове.
Вещи немного меняются. Используются те же самые операторы, но их значение становится значительно размытым.
Объектный оператор ->
по-прежнему используется для выполнения вызовов в состояние экземпляра объекта.
class Foo {
public $a = 1;
public function bar() {
return $this->a;
}
}
Вызов метода bar()
на $foo
(экземпляр Foo
) с помощью объекта-оператора: $foo->bar()
приведет к версии экземпляра $a
.
Итак, как мы ожидаем.
Значение оператора ::
меняется. Это зависит от контекста вызова текущей функции:
В статическом контексте
В статическом контексте любые вызовы, сделанные с помощью ::
, также будут статическими. Рассмотрим пример:
class Foo {
public function bar() {
return Foo::baz();
}
public function baz() {
return isset($this);
}
}
Вызов Foo::bar()
вызовет метод baz()
статически, и, следовательно, $this
будет заполнен not. Стоит отметить, что в последних версиях PHP (5.3+) это приведет к ошибке E_STRICT
, потому что мы статически ставим нестатические методы.
В контексте экземпляра
В контексте экземпляра, с другой стороны, вызовы с использованием ::
зависят от получателя вызова (метод, который мы вызываем). Если метод определен как static
, тогда он будет использовать статический вызов. Если это не так, он отправит информацию о экземпляре.
Итак, рассмотрев приведенный выше код, вызов $foo->bar()
вернет true
, поскольку "статический" вызов происходит внутри контекста экземпляра.
Имеют смысл? Не думал так. Это сбивает с толку.
Поскольку связывание всего вместе с использованием имен классов довольно грязно, PHP предоставляет 3 основных слова "ярлыка", чтобы облегчить разрешение области.
self
- Это относится к текущему имени класса. Итак, self::baz()
совпадает с Foo::baz()
в классе Foo
(любой метод на нем).
parent
- Это относится к родительскому элементу текущего класса.
static
- Это относится к вызываемому классу. Благодаря наследованию дочерние классы могут переопределять методы и статические свойства. Поэтому вызов их с помощью static
вместо имени класса позволяет нам решить, откуда пришел вызов, а не текущий уровень.
Самый простой способ понять это - начать изучать некоторые примеры. Выберем класс:
class Person {
public static $number = 0;
public $id = 0;
public function __construct() {
self::$number++;
$this->id = self::$number;
}
public $name = "";
public function getName() {
return $this->name;
}
public function getId() {
return $this->id;
}
}
class Child extends Person {
public $age = 0;
public function __construct($age) {
$this->age = $age;
parent::__construct();
}
public function getName() {
return 'child: ' . parent::getName();
}
}
Теперь мы также смотрим на наследование. Игнорируйте на мгновение, что это плохая модель объекта, но давайте посмотрим, что происходит, когда мы играем с этим:
$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3
Таким образом, счетчик ID используется как для обоих экземпляров, так и для детей (потому что мы используем self
для доступа к нему. Если мы использовали static
, мы могли бы переопределить его в дочернем классе).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Обратите внимание, что мы каждый раз выполняем метод экземпляра Person::getName()
. Но мы используем parent::getName()
, чтобы сделать это в одном из случаев (дочерний регистр). Именно это делает этот подход мощным.
Обратите внимание, что контекст вызова определяет, используется ли экземпляр. Поэтому:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Не всегда true.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Теперь это действительно странно. Мы вызываем другой класс, но $this
, который передается методу Foo::isFoo()
, является экземпляром $bar
.
Это может вызвать всевозможные ошибки и концептуальные WTF-ery. Поэтому я настоятельно рекомендую избегать оператора ::
из методов экземпляра на всех, кроме трех виртуальных "коротких сокращенных" ключевых слов (static
, self
и parent
).
Обратите внимание, что статические методы и свойства разделяются всеми. Это делает их в основном глобальными переменными. Со всеми теми же проблемами, что и с глобальными. Поэтому я был бы очень неспособен хранить информацию в статических методах/свойствах, если вам не нравится, что это действительно глобально.
В общем, вы захотите использовать то, что известно как Late-Static-Binding, используя static
вместо self
. Но обратите внимание, что они не одно и то же, поэтому "всегда использовать static
вместо self
действительно близоруки. Вместо этого остановитесь и подумайте о вызове, который хотите сделать, и подумайте, хотите ли вы, чтобы дочерние классы были в состоянии переопределить этот статический разрешенный вызов.
Слишком плохо, вернитесь и прочитайте. Это может быть слишком долго, но это так долго, потому что это сложная тема
Хорошо, отлично. Короче говоря, self
используется для ссылки на текущее имя класса в классе, где $this
ссылается на текущий экземпляр объекта. Обратите внимание, что self
является копией/вставкой. Вы можете спокойно заменить его своим именем класса, и он будет работать нормально. Но $this
- динамическая переменная, которая не может быть определена заранее (и может даже не быть вашим классом).
Если используется оператор-объект (->
), вы всегда знаете, что имеете дело с экземпляром. Если используется оператор-разрешающая способность (::
), вам нужна дополнительная информация о контексте (мы уже в объектном контексте? Являются ли мы вне объекта? И т.д.).
self
(не $self) относится к типу класса, где $this
относится к текущему экземпляру класса. self
предназначен для использования в статических функциях-членах, чтобы вы могли получать доступ к статическим переменным-членам. $this
используется в нестатических функциях-членах и является ссылкой на экземпляр класса, на который была вызвана функция-член.
Поскольку this
- это объект, вы используете его как: $this->member
Поскольку self
не является объектом, он в основном тип, который автоматически ссылается на текущий класс, вы используете его как: self::member
$this->
используется для обозначения конкретного экземпляра переменных класса (переменных-членов) или методов.
Example:
$derek = new Person();
$ derek теперь является конкретным экземпляром Person. У каждого человека есть first_name и last_name, но у $ derek есть определенное имя_имя и last_name (Дерек Мартин). Внутри экземпляра $ derek мы можем обращаться к ним как $this-> first_name и $this-> last_name
ClassName :: используется для обозначения этого типа класса и его статических переменных, статических методов. Если это поможет, вы можете мысленно заменить слово "статический" на "общий". Поскольку они являются общими, они не могут ссылаться на $ this, что относится к определенному экземпляру (не разделяемому). Статические переменные (т.е. статические $ db_connection) могут быть разделены между всеми экземплярами типа объекта. Например, все объекты базы данных используют одно соединение (статическое соединение $).
Статические переменные Пример: Представьте, что у нас есть класс базы данных с одной переменной-членом: static $ num_connections; Теперь поставьте это в конструкторе:
function __construct()
{
if(!isset $num_connections || $num_connections==null)
{
$num_connections=0;
}
else
{
$num_connections++;
}
}
Так же, как объекты имеют конструкторы, они также имеют деструкторы, которые выполняются, когда объект умирает или не работает:
function __destruct()
{
$num_connections--;
}
Каждый раз, когда мы создаем новый экземпляр, он увеличит счетчик соединений на один. Каждый раз, когда мы уничтожаем или останавливаем использование экземпляра, он уменьшает счетчик соединений на единицу. Таким образом, мы можем отслеживать количество экземпляров используемого объекта базы данных:
echo DB::num_connections;
Поскольку $ num_connections является статическим (общим), он будет отображать общее количество активных объектов базы данных. Возможно, вы видели эту технику, используемую для совместного использования соединений с базой данных среди всех экземпляров класса базы данных. Это делается потому, что создание соединения с базой данных занимает много времени, поэтому лучше всего создать только один и поделиться им (это называется шаблоном Singleton).
Статические методы (т.е. Public static View :: format_phone_number ($ digits)) можно использовать БЕЗ первого экземпляра одного из этих объектов (т.е. Они внутренне не ссылаются на $ this).
Пример статического метода:
public static function prettyName($first_name, $last_name)
{
echo ucfirst($first_name).' '.ucfirst($last_name);
}
echo Person::prettyName($derek->first_name, $derek->last_name);
Как вы можете видеть, public static function prettyName ничего не знает об объекте. Он просто работает с параметрами, которые вы проходите, как обычная функция, которая не является частью объекта. Зачем же беспокоиться, если бы мы могли просто иметь это не как часть объекта?
SELF :: Если вы кодируете вне объекта, у которого есть статический метод, к которому вы хотите обратиться, вы должны вызвать его, используя имя объекта View :: format_phone_number ($ phone_number); Если вы кодируете внутри объекта, у которого есть статический метод, к которому вы хотите обратиться, вы можете либо использовать имя объекта View :: format_phone_number ($ pn), либо вы можете использовать ярлык self :: format_phone_number ($ pn)
То же самое касается статических переменных: Пример: View :: templates_path versus self :: templates_path
Внутри класса DB, если бы мы ссылались на статический метод какого-либо другого объекта, мы использовали бы имя объекта: Example: Session :: getUsersOnline();
Но если класс DB хотел ссылаться на свою собственную статическую переменную, он просто сказал бы себя: Пример: self :: connection;
Надеюсь, что помогает разобраться :)
self
относится к текущему классуself
может использоваться для вызова статических функций и ссылки на статические переменные-членыself
может использоваться внутри статических функцийself
также может отключить полиморфное поведение, минуя vtable$this
относится к текущему объекту$this
может использоваться для вызова статических функций$this
не следует использовать для вызова статических переменных-членов. Вместо этого используйтеself
.$this
не может использоваться внутри статических функций
В PHP вы используете ключевое слово self для доступа к статическим свойствам и методам.
Проблема заключается в том, что вы можете заменить $this->method()
на self::method()
где угодно, независимо от того, объявлен ли method()
статическим или нет. Итак, какой из них следует использовать?
Рассмотрим этот код:
class ParentClass {
function test() {
self::who(); // will output 'parent'
$this->who(); // will output 'child'
}
function who() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function who() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
В этом примере self::who()
всегда будет выводить 'parent, а $this->who()
будет зависеть от того, какой класс имеет объект.
Теперь мы можем видеть, что self относится к классу, в котором он вызывается, а $this
относится к классу текущего объекта.
Итак, вы должны использовать self только тогда, когда $this
недоступен, или если вы не хотите, чтобы классы потомков перезаписывали текущий метод.
Внутри определения класса $this относится к текущему объекту, тогда как self относится к текущему классу.
Необходимо ссылаться на элемент класса, используя self, и ссылаться на элемент объекта, используя $this.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Согласно http://www.php.net/manual/en/language.oop5.static.php, нет $self
. Существует только $this
, для обращения к текущему экземпляру класса (объекта) и self, который может использоваться для ссылки на статические члены класса. Здесь происходит различие между экземпляром объекта и классом.
Вот пример правильного использования $this и self для нестатического и статические переменные-члены:
<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;
function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}
new X();
?>
self
относится к текущему классу (в котором он называется),
$this
относится к текущему объекту. Вы можете использовать static вместо self. См. Пример:
class ParentClass {
function test() {
self::which(); // output 'parent'
$this->which(); // output 'child'
}
function which() {
echo 'parent';
}
}
class ChildClass extends ParentClass {
function which() {
echo 'child';
}
}
$obj = new ChildClass();
$obj->test();
Выход: родительский ребенок
Я считаю, что вопрос не в том, можно ли вызвать статический член класса, вызвав ClassName::staticMember
. Вопрос в том, какая разница между использованием self::classmember
и $this->classmember
.
Например, оба следующих примера работают без каких-либо ошибок, независимо от того, используете ли вы: self::
или $this->
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
$this->name = $new_name;
$this->address = $new_address;
}
}
class Person{
private $name;
private $address;
public function __construct($new_name,$new_address){
self::$name = $new_name;
self::$address = $new_address;
}
}
См. следующий пример, показывающий перегрузку.
<?php
class A {
public static function newStaticClass()
{
return new static;
}
public static function newSelfClass()
{
return new self;
}
public function newThisClass()
{
return new $this;
}
}
class B extends A
{
public function newParentClass()
{
return new parent;
}
}
$b = new B;
var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A
class C extends B
{
public static function newSelfClass()
{
return new self;
}
}
$c = new C;
var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"
В большинстве случаев вы хотите обратиться к текущему классу, поэтому вы используете static
или $this
. Однако есть моменты, когда вам нужно self
, потому что вам нужен исходный класс, независимо от того, что его расширяет. (Очень, очень редко)
Поскольку здесь никто не говорил о спектаклях, вот небольшой тест, который я сделал (5.6):
Name | Time | Percent
----------|---------|---------
$this-> | 0.99163 | 106.23%
self:: | 0.96912 | 103.82%
static:: | 0.93348 | 100%
Это результаты для 2 000 000 прогонов, и вот код, который я использовал:
<?php
require '../vendor/autoload.php';
// My small class to do benchmarks
// All it does is looping over every test x times and record the
// time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);
class Foo
{
public function calling_this()
{
$this->called();
}
public function calling_self()
{
self::called();
}
public function calling_static()
{
static::called();
}
public static function called()
{
}
}
$b->add('$this->', function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::', function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });
$b->run();
Когда self
используется с оператором ::
, он ссылается на текущий класс, который может выполняться как в статическом, так и в нестационарном контексте. $this
относится к самому объекту. Кроме того, совершенно правильно использовать $this
для вызова статических методов (но не для ссылки на поля).
$this
относится к текущему объекту класса, self
относится к текущему классу (Not object). Класс - это проект объекта. Таким образом, вы определяете класс, но вы строите объекты.
Иными словами, используйте self for static
и this for none-static members or methods
.
также в сценарии child/parent self / parent
в основном используется для определения дочерних и родительских классов и методов.
Кроме того, поскольку $this::
еще не обсуждался.
Только в информационных целях, начиная с PHP 5.3, когда имеешь дело с экземплярами объектов, чтобы получить текущее значение области действия, в отличие от использования static::
, можно альтернативно использовать $this::
вот так.
class Foo
{
const NAME = 'Foo';
//Always Foo::NAME (Foo) due to self
protected static $staticName = self::NAME;
public function __construct()
{
echo $this::NAME;
}
public function getStaticName()
{
echo $this::$staticName;
}
}
class Bar extends Foo
{
const NAME = 'FooBar';
/**
* override getStaticName to output Bar::NAME
*/
public function getStaticName()
{
$this::$staticName = $this::NAME;
parent::getStaticName();
}
}
$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar
Использование приведенного выше кода не является общепринятой или рекомендуемой практикой, а просто иллюстрирует его использование и действует как "Знаете ли вы?" со ссылкой на оригинальный постер вопрос.
Он также представляет использование $object::CONSTANT
например, echo $foo::NAME;
в отличие от $this::NAME;
Используйте self
если вы хотите вызвать метод класса, не создавая объект/экземпляр этого класса, тем самым сохраняя RAM (иногда используйте self для этой цели). Другими словами, он на самом деле вызывает метод статически. Используйте this
для перспективы объекта.
Я столкнулся с тем же вопросом, и простой ответ:
Всякий раз, когда вы используете статические методы или статические атрибуты и хотите вызывать их, не создавая экземпляр класса, вам нужно использовать self :: для их вызова, потому что $ this всегда требуется для создания объекта.
Случай 1: Использовать self
можно для констант класса
class classA { const FIXED_NUMBER = 4; self::POUNDS_TO_KILOGRAMS }
Если вы хотите вызывать его вне класса, используйте classA::POUNDS_TO_KILOGRAMS
для доступа к константам
Случай 2: для статических свойств
class classC { public function __construct() { self::$_counter++; $this->num = self::$_counter; } }
Согласно php.net, в этом контексте есть три специальных ключевых слова: self
, parent
и static
. Они используются для доступа к свойствам или методам из определения класса.
$this
, с другой стороны, используется для вызова экземпляра и методов любого класса, если этот класс доступен.