Когда использовать self вместо $this?
Используйте $this для ссылки на текущий объект, а self — для ссылки на текущий класс. Другими словами, используйте $this->member для нестатических членов, а self::$member — для статических.
Полный ответ
Ниже приведен пример правильного использования $this и self для не статических и статических переменных-членов:
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 для нестатических и статических переменных-членов:
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 для функций-членов:
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 функций-членов:
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() любого точного типа текущего объекта. Если объект имеет тип X, то вызывается X::foo(). Если объект имеет тип Y, то вызывается Y::foo(). Но при использовании self::foo() всегда вызывается X::foo().
Ответ 2
Ключевое слово self НЕ относится только к « текущему классу » , по крайней мере, не так, чтобы ограничивать вас статическими членами. В контексте нестатического члена self также предоставляет возможность обойти 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().»
«;
>
public function sayGoodbye()
echo «Goodbye from «.self::getTitle().»
«;
>
>
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();
Это выведет:
Hello, I’m Ludwig the geek
Goodbye from Ludwig the person
sayHello() использует указатель $this, поэтому для вызова Geek::getTitle() вызывается vtable. sayGoodbye() использу ет self::getTitle(), поэтому vtable не используется, а вызывается Person::getTitle(). В обоих случаях мы имеем дело с методом инстанцированного объекта и имеем доступ к указателю $this внутри вызываемых функций.
Ответ 3
НЕ ИСПОЛЬЗУЙТЕ self. используйте static::
Есть еще один аспект self. о котором стоит упомянуть. Досадно, что self:: относится к области видимости в точке определения, а не в точке выполнения. Рассмотрим простой класс с двумя методами:
class Person
public static function status()
self::getStatus();
>
protected static function getStatus()
echo «Person is alive»;
>
>
Если мы вызовем Person::status(), то увидим « Person is alive » . Теперь рассмотрим, что произойдет, если мы создадим класс, который наследуется от него:
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:: реализует « позднюю статическую привязку » , что является интересным способом указать, что он привязан к области видимости вызываемого класса. Измените строку в status() на static::getStatus(), и результаты будут такими, как вы ожидаете. В более старых версиях PHP вам придется прибегнуть к хитрости, чтобы сделать это.
Итак, резюмируя…
$this-> относится к текущему объекту (экземпляру класса), тогда как static:: относится непосредственно к классу.
Ответ 4
Чтобы по-настоящему понять, о чем мы говорим, когда говорим о 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 .
Определение состояния
- Свойства — воспринимайте их как переменные, которые будет содержаться в каждом экземпляре.
- Статические свойства — воспринимайте их как переменные, которые раздел я ются на уровне класса. Это означает, что они никогда не копируются каждым экземпляром.
- Методы — это функции, которые будут содержаться в каждом экземпляре (и работать над экземплярами).
- Статические методы — это функции, общие для всего класса. Они не работают с экземплярами, только со статическими свойствами.
- Константы — класс разрешает использование констант. Не будем углубляться, но добавим для полноты:
Состояние и методы
Внутри метода экземпляр объекта представлен переменной $this. В ней находится текущее состояние этого объекта, и мутирование (изменение) любого свойства приведет к изменению этого экземпляра (но не других).
Если метод вызывается статически, переменная $this не определяется. Это происходит потому, что со статическим вызовом не ассоциируется ни один экземпляр.
Интересным здесь является то, как выполняются статические вызовы. Поэтому давайте поговорим о том, как мы получаем доступ к состоянию.
Состояние доступа
Итак, теперь, когда мы сохранили это состояние, нам нужно получить к нему доступ. Это может оказаться немного сложным, поэтому давайте разделим это на две точки зрения: снаружи экземпляра/класса (скажем, из обычного вызова функции или из глобальной области видимости) и внутри экземпляра/класса (из метода объекта).
Снаружи экземпляра/класса
- -> — объект-оператор — всегда используется, когда мы обращаемся к экземпляру.
- :: — scope-Resolution-operator — всегда используется для доступа к статическому свойству или методу класса.
Внутри экземпляра/класса
Краткие ключевые слова
- 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(), чтобы сделать это в одном из случаев (дочерний случай). Именно это и делает данный подход мощным.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
ЗлостныйКодер
У каждого обычно возникает вопрос, что такое $this, что такое self, для чего они используются и в чем разница между ними?
ПРАВИЛА КОТОРЫЕ ВЫ ДОЛЖНЫ ЗАПОМНИТЬ:
- Статические функции должны использовать только статические переменные.
- self ТОЛЬКО для статических функций, свойств. Но также можно вызвать нестатический метод, КАК СТАТИЧЕСКИЙ через self. Но лучше так не делать, а то папа побьет.
- this ТОЛЬКО для нестатических.
- this требует, чтобы класс был проинстанцирован, self не требует.
public function klassFunc() <>; function getName() echo $name; // неправильно, обратиться не к переменной public name echo $this->name; // правильно //вызов метода класса $this->klassFunc(); > >
Обычна нужна, чтобы инициализировать поля в конструкторе, ну и не только:
public function __construct($name)$name = $name; //будет ошибка$self используется в том, же самом ключе, но уже для СТАТИЧЕСКИХ свойств:
class human static $name = "ololo";public function klassFunc() <>; function getName() echo self::$name; //обращение к nameecho $this->name; //null или ошибка. НЕЛЬЗЯ > >Проверочная программа которая показывает главную разницу между self и $this:
class Klass const STAT = 'S' ; // константы всегда статичны static $stat = 'Static' ;
public $publ = 'Public' ;
private $priv = 'Private' ;
protected $prot = 'Protected' ;public function show ( ) print '
self::STAT: ' . self :: STAT ; // ссылается на константу
print '
self::$stat: ' . self :: $stat ; // статическая переменная.
print '
$this->stat: ' . $this -> stat ; // Ошибки нет, но выведет пустую строку. ПРЕДУПРЕЖДЕНИЕ.
print '
$this->publ: ' . $this -> publ ; // выведет как надо
print '
' ;
>
> $me = new Klass () ; $me -> show () ;Результат:
self::STAT: S
self::$stat: Static
Strict Standards: Accessing static property Klass::$stat as non static in htdocs\test\testReference.php on line ..
Notice: Undefined property: Klass::$stat in C:\xampp\htdocs\test\testReference.php on line 50
$this->stat:
$this->publ: Public
Видно, что php умный и кидает предупреждения глупым программистам. Не делайте так.Второе главное отличие состоит в том, что
self не использует таблицу виртуальных методов, то есть:
(взято с StackOverflow)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()."
"; > public function sayGoodbye() echo "Goodbye from ".self::getTitle()."
"; > > 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();Hello, I'm Ludwig the geek
Goodbye from Ludwig the personПояснение:
Метод sayHello использует this, поэтому виртуальная таблица вызовет Geek::getTitle()
Метод sayGoodbye использует self, поэтому виртуальная таблица будет не задействована и будет вызван parent::getTitle()Решение:
Используем вместо self, static keyword:
public function sayGoodbye() echo "Goodbye from ". static::getTitle() ;