Вопрос

В 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 делает НЕТ ссылайтесь просто на «текущий класс», по крайней мере, не ограничивая вас статическими членами.В контексте нестатического члена self также предоставляет способ обхода vtable (см. вики на 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 типов «вещей»:

  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.

Это может вызвать всевозможные ошибки и концептуальные WTF-еры.Поэтому я настоятельно рекомендую избегать :: оператор из методов экземпляра для чего угодно, кроме этих трех виртуальных «сокращенных» ключевых слов (static, self, и parent).

Слово предостережения № 2

Обратите внимание, что статические методы и свойства являются общими для всех.Это делает их по сути глобальными переменными.Со всеми теми же проблемами, что и с глобальными переменными.Поэтому я бы не стал хранить информацию в статических методах/свойствах, если вас не устраивает, что она действительно глобальна.

Слово предостережения №3

В общем, вы захотите использовать так называемое позднее статическое связывание, используя static вместо self.Но учтите, что это не одно и то же, поэтому поговорка «всегда используйте static вместо self действительно недальновидно.Вместо этого остановитесь и подумайте о вызове, который вы хотите сделать, и подумайте, хотите ли вы, чтобы дочерние классы могли его переопределить. статика решена вызов.

TL/DR

Жаль, вернитесь и прочитайте.Возможно, это слишком долго, но так долго, потому что это сложная тема.

TL/DR № 2

Хорошо.Суммируя, self используется для ссылки текущее имя класса внутри класса, где как $this относится к текущему объекту пример.Обратите внимание, что self это ярлык копирования/вставки.Вы можете безопасно заменить его именем своего класса, и все будет работать нормально.Но $this — это динамическая переменная, которую невозможно определить заранее (и которая может даже не быть вашим классом).

TL/DR #3

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

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

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

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

$this-> используется для ссылки на конкретный экземпляр переменных класса (переменных-членов) или методов.

Example: 
$derek = new Person();

$derek теперь является конкретным экземпляром Person.У каждого человека есть имя и фамилия, но у $derek есть определенные имя и фамилия (Дерек Мартин).Внутри экземпляра $derek мы можем ссылаться на них как $this->first_name и $this->last_name.

Имя Класса::используется для обозначения этого типа класса и его статических переменных, статических методов.Если это поможет, вы можете мысленно заменить слово «статический» на «общий».Поскольку они являются общими, они не могут ссылаться на $this, который относится к конкретному экземпляру (не общему).Статические переменные (т.е.static $db_connection) может использоваться всеми экземплярами типа объекта.Например, все объекты базы данных используют одно соединение (статическое $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 является статическим (общим), он будет отражать общее количество активных объектов базы данных.Возможно, вы видели, как этот метод используется для совместного использования соединений с базой данных всеми экземплярами класса базы данных.Это сделано потому, что создание подключения к базе данных занимает много времени, поэтому лучше создать только одно соединение и поделиться им (это называется шаблоном 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);

Как видите, публичная статическая функция PrettyName ничего не знает об объекте.Он просто работает с передаваемыми вами параметрами, как обычная функция, не являющаяся частью объекта.Зачем тогда беспокоиться, если мы можем просто иметь это не как часть объекта?

  1. Во-первых, прикрепление функций к объектам помогает вам сохранять порядок и знать, где их найти.
  2. Во-вторых, это предотвращает конфликты имен.В большом проекте функции getName(), скорее всего, будут создавать два разработчика.Если один создает ClassName1::getName(), а другой создает ClassName2::getName(), это вообще не проблема.Никакого конфликта.Ура статические методы!

СЕБЯ::Если вы кодируете снаружи объект, имеющий статический метод, на который вы хотите сослаться, вы должны вызвать его, используя имя объекта View::format_phone_number($phone_number);Если вы кодируете внутри объект, имеющий статический метод, на который вы хотите сослаться, вы можете или используйте имя объекта View::format_phone_number($pn) ИЛИ вы можете использовать ярлык self::format_phone_number($pn)

То же самое касается статических переменных:Пример: View::templates_path и self::templates_path

Внутри класса DB, если бы мы ссылались на статический метод какого-либо другого объекта, мы бы использовали имя объекта:Пример: Session::getUsersOnline();

Но если бы класс БД захотел сослаться на свою собственную статическую переменную, он бы просто сказал: 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 недоступен или если вы не хотите, чтобы классы-потомки перезаписывали текущий метод.

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

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

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  

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

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

Выход:родительский ребенок

  • Указатель объекта $this to ссылается на текущий объект.
  • Значение класса «статический» относится к текущему объекту.
  • Значение класса «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 потому что вам нужен исходный класс независимо от того, что его расширяет.(Очень, Очень редко)

Поскольку здесь никто не говорил о производительности, я сделал небольшой тест (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();

Я считаю, что вопрос заключался не в том, можете ли вы вызвать статический член класса, вызвав 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;
    }
}

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

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

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

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

Кроме того, поскольку $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;

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

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

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

Использовать 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;
   }
}

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top