Php classes this self

Когда использовать 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 » . Теперь рассмотрим, что произойдет, если мы создадим класс, который наследуется от него:

Читайте также:  IT SourceCode

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 .

Определение состояния

  1. Свойства — воспринимайте их как переменные, которые будет содержаться в каждом экземпляре.
  1. Статические свойства — воспринимайте их как переменные, которые раздел я ются на уровне класса. Это означает, что они никогда не копируются каждым экземпляром.
  1. Методы — это функции, которые будут содержаться в каждом экземпляре (и работать над экземплярами).
  1. Статические методы — это функции, общие для всего класса. Они не работают с экземплярами, только со статическими свойствами.
  1. Константы — класс разрешает использование констант. Не будем углубляться, но добавим для полноты:
Читайте также:  Header function in javascript

Состояние и методы

Внутри метода экземпляр объекта представлен переменной $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(), чтобы сделать это в одном из случаев (дочерний случай). Именно это и делает данный подход мощным.

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Читайте также:  Статистика дискорд бот python

Источник

ЗлостныйКодер

У каждого обычно возникает вопрос, что такое $this, что такое self, для чего они используются и в чем разница между ними?
ПРАВИЛА КОТОРЫЕ ВЫ ДОЛЖНЫ ЗАПОМНИТЬ:

  1. Статические функции должны использовать только статические переменные.
  2. self ТОЛЬКО для статических функций, свойств. Но также можно вызвать нестатический метод, КАК СТАТИЧЕСКИЙ через self. Но лучше так не делать, а то папа побьет.
  3. this ТОЛЬКО для нестатических.
  4. 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; //обращение к name
echo $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() ;

Источник

Оцените статью