Когда использовать self за $это?


В PHP 5, в чем разница между использованием self и $this?

Когда каждый из них подходит?

 1802
Author: 7ochem, 2008-09-30

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:

По http://board.phpbuilder.com/member.php?145249-laserlight

 1527
Author: John Millikin, 2016-07-28 06:04:22

Ключевое слово 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 в вызываемых функциях.

 712
Author: nbeagle, 2014-11-10 08:37:04

НЕ ИСПОЛЬЗУЙТЕ 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:: относится к классу

 430
Author: Sqoo, 2018-07-04 08:01:45

Чтобы действительно понять, о чем мы говорим, когда говорим о 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 типов "вещей", которые содержит класс:

  1. Свойства - Думайте о них как о переменных, которые будут содержать каждый экземпляр.

    class Foo {
        public $bar = 1;
    }
    
  2. Статические свойства - Думайте о них как о переменных, которые являются общими на уровне класса. Это означает, что они никогда не копируются каждым экземпляром.

    class Foo {
        public static $bar = 1;
    }
    
  3. Методы - Это функции, которые будут содержать каждый экземпляр (и работать на экземпляры).

    class Foo {
        public function bar() {}
    }
    
  4. Статические методы - Это функции, которые являются общими для всего класса. Они не работают с экземплярами, а только со статическими свойствами.

    class Foo {
        public static function bar() {}
    }
    
  5. Константы - разрешенные константы класса. Не углубляясь здесь, но добавляя для полноты:

    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

Если используется оператор объекта (->), то вы всегда знаете, что имеете дело с экземпляром. Если используется оператор разрешения области действия (::), вам нужна дополнительная информация о контексте (мы уже находимся в контексте объекта? Находимся ли мы вне объекта? и т.д.).

 231
Author: ircmaxell, 2017-05-23 11:33:26

self ( не $self) относится к типу класса, где as $this относится к текущему экземпляру класса. self предназначен для использования в статических функциях-членах, чтобы разрешить вам доступ к статическим переменным-членам. $this используется в нестатических функциях-членах и является ссылкой на экземпляр класса, в котором была вызвана функция-член.

Поскольку this является объектом, вы используете его как: $this->member

Поскольку self не является объектом, это в основном тип, который автоматически ссылается на текущий класс, вы используете его как: self::member

 109
Author: MrZebra, 2013-05-06 09:49:23

$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 ничего не знает об объекте. Это просто работа с параметрами, которые вы передаете, как обычная функция, которая не является частью объекта. Зачем тогда беспокоиться, если мы могли бы просто иметь это не как часть объекта?

  1. Во-первых, прикрепление функций к объектам помогает вам упорядочивать вещи, чтобы вы знали, где их найти.
  2. Второй, это предотвращает конфликты именования. В большом проекте у вас, скорее всего, будет два разработчика, создающих функции 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::соединение;

Надеюсь, это поможет прояснить ситуацию:)

 93
Author: lo_fye, 2018-02-16 14:10:47

Из этого сообщения в блоге:

  • self относится к текущему классу
  • self может использоваться для вызова статических функций и ссылки на статические переменные-члены
  • self может использоваться внутри статических функций
  • self также можно отключить полиморфное поведение, обойдя таблицу vtable
  • $this относится к текущему объекту
  • $this может использоваться для вызова статических функций
  • $this не следует использовать для вызова статических переменных-членов. Вместо этого используйте self.
  • $this не может использоваться внутри статических функций
 27
Author: okconfused, 2014-01-24 15:46:59

В 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 недоступен или когда вы не хотите разрешать классам-потомкам перезаписывать текущий метод.

 23
Author: ramin rostami, 2017-06-28 17:06:03

Внутри определения класса $это относится к текущему объекту, в то время как self относится к текущему классу.

Необходимо ссылаться на элемент класса, используя self, и ссылаться на элемент объекта, используя $this.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
 19
Author: Tarun Singhal, 2015-12-14 12:57:19

Вот пример правильного использования $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();
?> 
 17
Author: Mohit Bumb, 2011-12-06 11:26:22

В соответствии с http://www.php.net/manual/en/language.oop5.static.php нет $self. Существует только $this для ссылки на текущий экземпляр класса (объект) и self, которые можно использовать для ссылки на статические члены класса. Здесь в игру вступает разница между экземпляром объекта и классом.

 16
Author: cruizer, 2018-02-16 14:10:30

Поскольку здесь никто не говорил о выступлениях, вот небольшой тест, который я сделал (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();
 12
Author: tleb, 2015-10-01 05:04:55

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();

Вывод: родитель ребенок

 12
Author: Kabir Hossain, 2018-02-16 14:12:42

Я полагаю, что вопрос не в том, можно ли вызвать статический член класса, вызвав 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;
    }
}
 11
Author: Akintunde-Rotimi, 2018-02-16 14:11:20
  • Указатель на объект $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 потому что вам нужен исходный класс, независимо от того, что его расширяет. (Очень, очень редко)

 10
Author: Xeoncross, 2013-03-22 15:30:00

Когда self используется с оператором ::, он ссылается на текущий класс, что может быть сделано как в статическом, так и в нестатическом контекстах. $this относится к самому объекту. Кроме того, совершенно законно использовать $this для вызова статических методов (но не для ссылки на поля).

 10
Author: mrDjouk, 2013-03-22 15:34:05

$this относится к текущему объекту класса, self относится к текущему классу (не объекту). Класс - это схема объекта. Таким образом, вы определяете класс, но создаете объекты.

Другими словами, используйте self for static и this for none-static members or methods.

Также в сценарии ребенок/родительself / parent в основном используется для идентификации дочерних и родительских членов класса и методов.

 5
Author: Rakesh Singh, 2014-09-15 06:36:28

Дополнительно, поскольку $this:: еще не обсуждалось.

Только в информационных целях, начиная с PHP 5.3, при работе с созданными объектами для получения текущего значения области, в отличие от использования static::, можно в качестве альтернативы использовать $this::, например.

Http://ideone.com/7etRHy

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;

 5
Author: fyrye, 2015-10-14 17:02:26

Используйте self, если вы хотите вызвать метод класса без создания объекта/экземпляра этого класса, таким образом экономя оперативную память (иногда используйте self для этой цели). Другими словами, это фактически статический вызов метода. Используйте this для перспективы объекта.

 4
Author: minhajul, 2018-02-16 14:12:05

Случай 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;
   }
}
 1
Author: li bing zhao, 2016-02-02 21:14:00

Я столкнулся с тем же вопросом, и простой ответ таков:

  • $для этого требуется экземпляр класса
  • self:: не

Всякий раз, когда вы используете статические методы или статические атрибуты и хотите вызвать их без создания экземпляра объекта класса, вам нужно использовать self:: для их вызова, потому что $это всегда требует создания объекта.

 1
Author: Mike, 2018-05-19 15:23:49

В соответствии с php.net в этом контексте есть три специальных ключевых слова: self, parent и static. Они используются для доступа к свойствам или методам изнутри определения класса.

$this, с другой стороны, используется для вызова экземпляра и методов любого класса, пока этот класс доступен.

 0
Author: Fil, 2015-12-07 12:26:21