Когда использовать self за $это?
В PHP 5, в чем разница между использованием self
и $this
?
Когда каждый из них подходит?
22 answers
Краткий ответ
Используйте
$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:
Ключевое слово self НЕ относится просто к "текущему классу", по крайней мере, не таким образом, чтобы ограничивать вас статическими членами. В контексте нестатического элемента 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();
Это будет вывод:
Привет, я Людвиг выродок
До свидания от Людвига человека
sayHello()
использует указатель $this
, поэтому виртуальная таблица вызывается для вызова 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()
, мы ожидали бы увидеть "Человек умер". однако мы видим, что "Человек жив", поскольку область содержит исходное определение метода, когда был определен вызов self::getStatus()
.
В PHP 5.3 есть решение. в static::
оператор разрешения реализует "позднюю статическую привязку", что является причудливым способом сказать, что он привязан к области действия вызываемого класса. Измените строку в status()
на static::getStatus()
, и результаты будут такими, как вы ожидали. В более старых версиях PHP для этого вам придется найти клудж.
См. PHP Документация
Итак, чтобы ответить на вопрос не так, как его задали...
$this->
относится к текущему объекту (экземпляру класса), тогда как static::
относится к классу
Чтобы действительно понять, о чем мы говорим, когда говорим о self
по сравнению с $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
не определена . Это потому, что есть нет экземпляра, связанного со статическим вызовом.
Здесь интересно то, как выполняются статические вызовы. Итак, давайте поговорим о том, как мы получаем доступ к состоянию:
Состояние доступа
Итак, теперь, когда мы сохранили это состояние, нам нужно получить к нему доступ. Это может быть немного сложно (или способ более чем немного), поэтому давайте разделим это на две точки зрения: извне экземпляра/класса (скажем, из обычного вызова функции или из глобальной области) и внутри экземпляра/класса (из в рамках метода на объекте).
Извне Экземпляра/Класса
За пределами экземпляра/класса наши правила довольно просты и предсказуемы. У нас есть два оператора, и каждый из них сразу сообщает нам, имеем ли мы дело с экземпляром или статическим классом:
-
->
- объект-оператор - Это всегда используется, когда мы обращаемся к экземпляру.$bob = new Person; echo $bob->name;
Важно отметить, что вызов
Person->foo
не имеет смысла (посколькуPerson
- это класс, а не экземпляр). Следовательно, это ошибка синтаксического анализа. -
::
- оператор разрешения области действия - Всегда используется для доступа к статическому свойству или методу класса.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
вызовет не быть заполненным. Стоит отметить, что в последних версиях 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
Таким образом, счетчик идентификаторов является общим для обоих экземпляров и дочерних элементов (потому что мы используем self
для доступа к нему. Если бы мы использовали static
, мы могли бы переопределить его в дочернем классе).
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
Обратите внимание, что мы выполняем Person::getName()
метод экземпляра каждый раз. Но мы используем parent::getName()
, чтобы сделать это в одном из случаев (случай с ребенком). Это то, что делает этот подход мощным.
Предостережение #1
Обратите внимание, что контекст вызова определяет, используется ли экземпляр. Следовательно:
class Foo {
public function isFoo() {
return $this instanceof Foo;
}
}
Не является всегда истинным.
class Bar {
public function doSomething() {
return Foo::isFoo();
}
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)
Теперь здесь действительно странно. Мы вызываем другой класс, но $this
, который передается методу Foo::isFoo()
, является пример $bar
.
Это может привести к всевозможным ошибкам и концептуальным ошибкам. Поэтому я настоятельно рекомендую избегать оператора ::
из методов экземпляра для всего, кроме этих трех виртуальных "коротких" ключевых слов (static
, self
, и parent
).
Предостережение #2
Обратите внимание, что статические методы и свойства являются общими для всех. Это делает их в основном глобальными переменными. Со всеми теми же проблемами, которые возникают с глобалами. Так что я бы действительно колебался хранить информацию в статических методах/свойствах, если вас не устраивает, что она действительно глобальная.
Предостережение #3
В общем случае вы захотите использовать так называемую Позднюю статическую привязку, используя static
вместо self
. Но обратите внимание, что это не одно и то же, поэтому говорить "всегда используйте static
вместо self
действительно недальновидно. Вместо этого остановитесь и подумайте о вызове, который вы хотите сделать, и подумайте, хотите ли вы, чтобы дочерние классы могли переопределять этот статический разрешен вызов.
TL/DR
Очень жаль, вернитесь и прочтите это. Это может быть слишком долго, но это так долго, потому что это сложная тема
TL/DR #2
Хорошо, хорошо. Короче говоря, self
используется для ссылки на текущее имя класса внутри класса, где как $this
относится к текущему объекту экземпляр . Обратите внимание, что self
- это сокращенное копирование/вставка. Вы можете безопасно заменить его своим именем класса, и он будет работать нормально. Но $this
является динамичным переменная, которая не может быть определена заранее (и может даже не быть вашим классом).
TL/DR #3
Если используется оператор объекта (->
), то вы всегда знаете, что имеете дело с экземпляром. Если используется оператор разрешения области действия (::
), вам нужна дополнительная информация о контексте (мы уже находимся в контексте объекта? Находимся ли мы вне объекта? и т.д.).
self
( не $self) относится к типу класса, где as $this
относится к текущему экземпляру класса. self
предназначен для использования в статических функциях-членах, чтобы разрешить вам доступ к статическим переменным-членам. $this
используется в нестатических функциях-членах и является ссылкой на экземпляр класса, в котором была вызвана функция-член.
Поскольку this
является объектом, вы используете его как: $this->member
Поскольку self
не является объектом, это в основном тип, который автоматически ссылается на текущий класс, вы используете его как: self::member
$this->
используется для ссылки на конкретный экземпляр переменных класса (переменных-членов) или методов.
Example:
$derek = new Person();
$дерек теперь является конкретным экземпляром Человека. У каждого человека есть имя и фамилия, но у $дерека есть определенное имя и фамилия (Дерек Мартин). Внутри экземпляра $derek мы можем ссылаться на них как на $this->имя_файла и $this->имя_файла
Имя класса:: используется для обозначения этого типа класса и его статических переменных, статических методов. Если это поможет, вы можете мысленно заменить слово "статический" на "общий". Поскольку они являются общими, они не могут ссылаться на $this, который ссылается на конкретный экземпляр (не общий). Статические переменные (т. Е. статические $db_connection) могут быть общими для всех экземпляров объекта определенного типа. Например, все объекты базы данных совместно используют одно соединение (статическое соединение $).
Пример статических переменных: Представьте, что у нас есть класс базы данных с одной переменной-членом: статический $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 - это статический (общий), он будет отражать общее количество активных объектов базы данных. Возможно, вы видели этот метод, используемый для совместного использования подключений к базе данных между всеми экземплярами класса базы данных. Это делается потому, что создание подключения к базе данных занимает много времени, поэтому лучше всего создать только одно и поделиться им (это называется одноэлементным шаблоном).
Статические методы (т.Е. общедоступное статическое представление::format_phone_number($цифры)) можно использовать БЕЗ создания первого экземпляра одного из этих объектов (т.Е. Они не ссылайтесь внутренне на $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);
Как вы можете видеть, публичная статическая функция prettyName ничего не знает об объекте. Это просто работа с параметрами, которые вы передаете, как обычная функция, которая не является частью объекта. Зачем тогда беспокоиться, если мы могли бы просто иметь это не как часть объекта?
- Во-первых, прикрепление функций к объектам помогает вам упорядочивать вещи, чтобы вы знали, где их найти.
- Второй, это предотвращает конфликты именования. В большом проекте у вас, скорее всего, будет два разработчика, создающих функции getName(). Если один создает ClassName1::getName(), а другой создает ClassName2::getName(), это вообще не проблема. Никакого конфликта. Ура статическим методам!
Я:: Если вы кодируете вне объекта, имеющего статический метод, на который вы хотите сослаться, вы должны вызвать его, используя имя объекта View::format_phone_number ($phone_number); Если вы кодируете внутри объекта, имеющего статический метод, на который вы хотите сослаться, вы можете либо использовать представление имени объекта::format_phone_number($pn), ЛИБО использовать ярлык self::format_phone_number($pn)
То же самое относится и к статическим переменным: Пример: Просмотр::templates_path по сравнению с самим собой::templates_path
Внутри класса БД, если бы мы ссылались на статический метод какого-либо другого объекта, мы бы использовали имя объекта: Пример: Сессия::Getusersonline();
Но если бы класс БД хотел ссылаться на свою собственную статическую переменную, он бы просто сказал self: Пример: self::соединение;
Надеюсь, это поможет прояснить ситуацию:)
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()
всегда будет выводить "родительский", в то время как $this->who()
будет зависеть от того, какой класс имеет объект.
Теперь мы можем видеть, что self относится к классу, в котором он вызывается, в то время как $this
относится к класс текущего объекта.
Таким образом, вы должны использовать self только тогда, когда $this
недоступен или когда вы не хотите разрешать классам-потомкам перезаписывать текущий метод.
Внутри определения класса $это относится к текущему объекту, в то время как self относится к текущему классу.
Необходимо ссылаться на элемент класса, используя self, и ссылаться на элемент объекта, используя $this.
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Вот пример правильного использования $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();
?>
В соответствии с http://www.php.net/manual/en/language.oop5.static.php нет $self
. Существует только $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
ссылается на текущий объект.
Вы можете использовать статику вместо себя.
Смотрите пример:
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;
}
}
- Указатель на объект $this указывает на текущий объект.
- Значение класса "статический" относится к текущему объекту.
- Значение класса "self" относится к точному классу, в котором оно было определено.
- Значение класса "родитель" относится к родителю точного класса, в котором он был определен.
См. Следующий пример, в котором показана перегрузка.
<?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
потому что вам нужен исходный класс, независимо от того, что его расширяет. (Очень, очень редко)
Когда self
используется с оператором ::
, он ссылается на текущий класс, что может быть сделано как в статическом, так и в нестатическом контекстах. $this
относится к самому объекту. Кроме того, совершенно законно использовать $this
для вызова статических методов (но не для ссылки на поля).
$this
относится к текущему объекту класса, self
относится к текущему классу (не объекту). Класс - это схема объекта. Таким образом, вы определяете класс, но создаете объекты.
Другими словами, используйте self for static
и this for none-static members or methods
.
Также в сценарии ребенок/родитель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
, если вы хотите вызвать метод класса без создания объекта/экземпляра этого класса, таким образом экономя оперативную память (иногда используйте 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; } }
Я столкнулся с тем же вопросом, и простой ответ таков:
- $для этого требуется экземпляр класса
- self:: не
Всякий раз, когда вы используете статические методы или статические атрибуты и хотите вызвать их без создания экземпляра объекта класса, вам нужно использовать self:: для их вызова, потому что $это всегда требует создания объекта.
В соответствии с php.net в этом контексте есть три специальных ключевых слова: self
, parent
и static
. Они используются для доступа к свойствам или методам изнутри определения класса.
$this
, с другой стороны, используется для вызова экземпляра и методов любого класса, пока этот класс доступен.