Когда использовать себя сверх $this?

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

Когда каждый уместен?

24 ответа

Решение

Короткий ответ

использование $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 указатель, поэтому vtable вызывается для вызова 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:: Оператор Resolution реализует "позднюю статическую привязку", которая является причудливым способом сказать, что она связана с областью действия вызываемого класса. Изменить строку в status() в static::getStatus() и результаты - это то, что вы ожидаете. В более старых версиях PHP вам нужно будет найти kludge для этого.

Смотрите 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 переменная не определена. Это потому, что нет никакого экземпляра, связанного со статическим вызовом.

Здесь интересно то, как выполняются статические звонки. Итак, давайте поговорим о том, как мы получаем доступ к состоянию:

Доступ к государству

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

Снаружи экземпляра / класса

Снаружи экземпляра / класса наши правила довольно просты и предсказуемы. У нас есть два оператора, и каждый сразу сообщает нам, имеем ли мы дело с экземпляром или классом static:

  • -> - object-operator - всегда используется при доступе к экземпляру.

    $bob = new Person;
    echo $bob->name;
    

    Важно отметить, что звонки Person->foo не имеет смысла (так как Person это класс, а не экземпляр). Следовательно, это ошибка разбора.

  • :: - scope-resolution-operator - всегда используется для доступа к статическому свойству или методу Class.

    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

В общем, вы захотите использовать то, что известно как Late-Static-Binding, используя 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

ClassName:: используется для ссылки на этот тип класса и его статические переменные, статические методы. Если это поможет, вы можете мысленно заменить слово "статический" на "общий". Поскольку они являются общими, они не могут ссылаться на $this, что относится к конкретному экземпляру (не общему). Статические переменные (т. Е. Статические $db_connection) могут быть общими для всех экземпляров типа объекта. Например, все объекты базы данных совместно используют одно соединение (статическое соединение $).

Пример статических переменных: представьте, что у нас есть класс базы данных с одной переменной-членом: static $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 Pattern).

Статические методы (т. Е. Общедоступный статический 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(), это не проблема. Нет конфликта Yay статические методы!

SELF:: Если вы кодируете вне объекта, который имеет статический метод, на который вы хотите сослаться, вы должны вызвать его, используя имя объекта 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 ();

Но если бы класс DB хотел ссылаться на свою собственную статическую переменную, он просто сказал бы: Self: Example: self:: connection;

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

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

  • 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() будет зависеть от того, какой класс имеет объект.

Теперь мы можем видеть, что "я" относится к классу, в котором оно называется, а $this ссылается на класс текущего объекта.

Таким образом, вы должны использовать себя только тогда, когда $this недоступен, или если вы не хотите, чтобы классы-потомки перезаписывали текущий метод.

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

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

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

  • Указатель на объект $this указывает на текущий объект.
  • Значение класса "static" относится к текущему объекту.
  • Значение класса "self" относится к точному классу, в котором оно было определено.
  • Значение класса "parent" относится к родителю того класса, в котором он был определен.

Смотрите следующий пример, который показывает перегрузку.

<?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 потому что вы хотите оригинальный класс независимо от того, что расширяет его. (Очень, очень редко)

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

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

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

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

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

 Ключевое слово self:: ключевое слово, используемое для текущего класса, и в основном оно используется для доступа к статическим членам, методам и константам. Но в случае $this вы не можете вызывать статический член, метод и функции.

Вы можете использовать ключевое слово self:: в другом классе и получить доступ к статическим членам, методу и константам. Когда он будет расширен от родительского класса и то же самое в случае ключевого слова $this. Вы можете получить доступ к нестатическим членам, методу и функции в другом классе, когда он будет расширяться от родительского класса.

Приведенный ниже код является примером ключевого слова self:: и $this. Просто скопируйте и вставьте код в свой файл кода и посмотрите результат.

class cars{
    var $doors=4;   
    static $car_wheel=4;

  public function car_features(){
    echo $this->doors." Doors <br>";
    echo self::$car_wheel." Wheels <br>"; 
  }
}

class spec extends cars{
    function car_spec(){
        print(self::$car_wheel." Doors <br>");
        print($this->doors." Wheels <br>");
    }
}

/********Parent class output*********/

$car = new cars;
print_r($car->car_features());

echo "------------------------<br>";

/********Extend class from another class output**********/


$car_spec_show=new spec;

print($car_spec_show->car_spec());

Случай 1: использование self может использоваться для констант класса

 class classA { 
     const FIXED_NUMBER = 4; 
     самостоятельно::POUNDS_TO_KILOGRAMS
}

Если вы хотите позвонить вне класса, используйте classA::POUNDS_TO_KILOGRAMS для доступа к константам

Случай 2: для статических свойств

class classC {
     публичная функция __construct() { 
     самостоятельно::$_ счетчик ++; $this->num = self::$_counter;
   }
}

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

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

Хотя это старый вопрос, я, как новичок, считаю полезным следующее сравнение. Особенно правила и синтаксис, необходимые для использования сselfи$this.

      
// A. Definitions
   
// Three classes bar1 for parallel use, and bar2 and bar3 for linear use;

class bar1 {
    // Class bar1 to use the object method "$this",
    // to create multiple parallel instances;
    
    public $foo = 111; // Property "$foo" set without "static" keyword; 
    // because we will be using the object method "$this",
    // to create multiple (unique and fresh) instances;
    
    public function getfoo() {
        return $this->foo; // Function "getfoo" returns the value of property "foo";
        // While calling the property using "$this", no "$" symbol is used; 
        // By calling our class "bar1" using "$this" instead of "self", 
        // we can use on multiple instances;
    }
    public function setfoo($foo) {
        $this->foo = $foo; // Function "setfoo" sets the value of property "foo"; 
        // While calling the property using "$this", no "$" symbol is used; 
        // By calling our class "bar1" using "$this" instead of "self", 
        // we can use on multiple instances;
    }
}

class bar2 {
    // Class bar2 to use the static method "self" to use as single linear instance;
    // Note the use of "::" (scope resolution operator) instead of object call "->" 
    
    public static $foo = 111; // Property "$foo" set with "static" keyword; 
        // because we will be using the static method "self" to use as single instance;
    
    public static function getfoo() {
        return self::$foo; // Function "getfoo" returns the value of property "foo"; 
        // While calling the property using "self", "$" symbol is necessary; 
        // We are calling our class "bar2" using "self" instead of "$this", 
        // because we are using static method "self" to use as single instance;
    }
    public static function setfoo($foo) {
        self::$foo = $foo; // Function "setfoo" sets the value of property "foo"; 
        // While calling the property using "self", "$" symbol is necessary; 
        // We are calling our class "bar2" using "self" instead of $this, 
        // because we are using static method "self" to use as single instance;
    }
}

class bar3 {
    // Class bar3 is same as bar2 and uses the static method "self", 
    // except it sets the property "$foo" using "__construct" constructor method;
    // so it can be used as a single linear instance,
    // which can be optionally reset/reinitialized;
    
    public static $foo; // Property "$foo" initialized with "static" keyword;
        // No value is set here because we are setting it using "__construct" instead;
        
    public function __construct() { // "__construct" will set the property values
        self::$foo = 111;
    }
    
    public static function getfoo() {
        return self::$foo;
    }
    public static function setfoo($foo) {
        self::$foo = $foo;
    }
}

// B. Tests


// B.1 Object method; Parallel instances $x and $y;

$x = new bar1(); // Fresh instance $x
echo $x->getfoo().PHP_EOL; // Output: 111 
$x->setfoo(123); // Updated instance $x
echo $x->getfoo().PHP_EOL.PHP_EOL; // Output: 123

$y = new bar1(); // Fresh instance $y
echo $y->getfoo().PHP_EOL; // Output: 111 
$y->setfoo(143); // Updated instance $y
echo $y->getfoo().PHP_EOL.PHP_EOL; // Output: 143


// B.2 Static method; Single linear instance;

new bar2(); // Not a fresh instance; Can be omitted;
echo bar2::getfoo().PHP_EOL; // Output: 111 
bar2::setfoo(123); // Updated the same static instance
echo bar2::getfoo().PHP_EOL.PHP_EOL; // Output: 123 

new bar2(); // Not a fresh instance; Can be omitted;
echo bar2::getfoo().PHP_EOL; // Output: 123
bar2::setfoo(143); // Updated the same static instance
echo bar2::getfoo().PHP_EOL.PHP_EOL; // Output: 143


// B.3 Static method using __construct; Single linear yet re-settable instance;

new bar3(); // Resets into a fresh instance; Omitting this line will reuse old instance;
echo bar3::getfoo().PHP_EOL; // Output: 111 
bar3::setfoo(123); // Updated the same static instance
echo bar3::getfoo().PHP_EOL.PHP_EOL; // Output: 123 

new bar3(); // Resets into a fresh instance; Omitting this line will reuse old instance;
echo bar3::getfoo().PHP_EOL; // Output: 111
bar3::setfoo(143); // Updated the same static instance
echo bar3::getfoo().PHP_EOL.PHP_EOL; // Output: 143

Другие вопросы по тегам