Питання Коли використовувати самообслуговування понад $ це?


У PHP 5, яка різниця між використанням self і $this?

Коли кожен підходить?


1777
2017-09-30 06:23


походження


можливий дублікат Новий сам проти нового статичного - Orangepill
Я збираюся запитати, яка різниця між: cont A; $ this-> A і self :: A - mboullouz


Відповіді:


Коротка відповідь

Використовуйте $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-лазерlight


1512
2017-09-30 06:29



Ця відповідь надто спрощена. Як зазначають інші відповіді, self використовується з оператором роздільної здатності :: посилання на поточний клас; це можна зробити як в статичних, так і в нестатичних контекстах. Крім того, це абсолютно законно використовувати $this викликати статичні методи (але не для посилань полів). - Artefacto
Також рекомендую використовувати статичний :: замість :: самостійно, якщо ви на 5.3+. В іншому випадку це може призвести до незрозумілих головних болів, подивіться на мою відповідь нижче. - Sqoo
-1. Ця відповідь є оманливою, читати інші відповіді для отримання додаткової інформації. - Pacerier
Це може бути занадто спрощено, але він відповідав на мій базовий рівень питання, не змусивши голову вибухнути. Я отримав деяку додаткову інформацію, яку я виявив корисною далі, але наразі я просто намагався з'ясувати, чому я потрапив до атрибутів класу за допомогою $ this-> attrib і константи класу з self :: constant. Це допомогло мені зрозуміти, що краще - MydKnight
А як на рахунок $this::? - James


Ключове слово самостійно робить НЕ зверніться лише до "поточного класу", принаймні, не таким чином, щоб обмежити вас статичними членами. У контексті нестатичного члена 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 покажчик всередині викликаних функцій.


710
2017-07-27 18:00



Ця відповідь буде ще краще, якщо ви почнете з загального правила, а не винятку. Це питання стилю, а не технічної експертизи. Це найкращий приклад, який я коли-небудь бачив у відмінності між self :: і $ this->, але ганьби це сховати, спочатку спростовуючи поняття. - adjwilli
@Adjwilli: Чому цей поганий стиль? Чи не спричиняє це свідомість, якщо очікування (теза) ОР спочатку не схвалюється (антитеза), а потім пояснення дається як синтез? - hakre
Я вважаю, що "поточний клас" дійсно проблематичний. Оскільки словосполучення можна розуміти як "клас" де self знаходиться "/" визначення класу це букварна частина ", а також" клас об'єкта "(що насправді буде static) - Jakumi
А як на рахунок $this::? - James


НЕ ВИКОРИСТОВУВАТИ 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 вам доведеться знайти kludge для цього.

Побачити PHP документація

Так що відповісти на питання не так, як просили ...

$this-> відноситься до поточного об'єкта (екземпляр класу), тоді як static::відноситься до класу


429
2017-07-24 15:08



А як щодо констант класу? - Kevin Bond
Я думаю, те ж саме йде - Sqoo
"Calling Deaded :: status (), ми очікуємо побачити" Person is dead "". Ні. Це статичний виклик функції, так що не існує жодного поліморфізму. - cquezel
@jaondavis спасибі, я намагався використовувати англійську та уникати таких термінів, як поліморфізм. Ця відповідь, як правило, складається з точки зору лише комп'ютерний вчений зрозуміє, PHP не є мовою, націленою на комп'ютерних вчених! - Sqoo
Приклад здається мені заплутаним: я бачу getStatus метод, яким я б вимагав екземпляр класу, а не для класу. - Jānis Elmeris


Щоб дійсно зрозуміти, про що ми говоримо, коли ми говоримо self проти $this, ми повинні фактично копатися в тому, що відбувається на концептуальному та практичному рівні. Я насправді не відчуваю, що жоден з відповідей це правильно, так що ось моя спроба.

Почнемо, поговоримо про те, що клас і а об'єкт є

Класи та об'єкти, концептуально

І що є a клас? Багато людей визначають це як креслення або a шаблон для об'єкта. Фактично, ви можете прочитати більше Про класів у 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:

  • -> - об'єкт-оператор - Це завжди використовується, коли ми отримуємо доступ до екземпляра.

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

    Важливо відзначити це дзвінок Person->foo не має сенсу (оскільки Person це клас, а не примірник). Тому це помилка розбору.

  • :: - оператор масштабу-резолюції - Це завжди використовується для доступу до класової статичної властивості або методу.

    echo Foo::bar()
    

    Крім того, ми можемо викликати статичний метод на об'єкт таким же чином:

    echo $foo::bar()
    

    Його надзвичайно Важливо відзначити, що коли ми це робимо ззовні, екземпляр об'єкта приховано від bar() метод Це означає, що це точно так само, як біг:

    $class = get_class($foo);
    $class::bar();
    

Тому $this не визначено в статичному дзвінку.

Зсередини інстанції / класу

Тут дещо змінюються. Такі ж оператори використовуються, але їх значення стає суттєво розмитим.

The об'єкт-оператор  -> як і раніше використовується для здійснення дзвінків на стан екземпляра об'єкта.

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-ery. Тому я дуже рекомендую уникати :: оператор з методів екземпляра на щось, окрім цих трьох віртуальних "коротких" ключових слів (static, self, і parent)

Слово обережності # 2

Зауважте, що статичні методи та властивості використовуються усіма. Це робить їх в основному глобальними змінами. З усіма тими ж проблемами, що постають з globals. Тому я б не хотів би зберігати інформацію в статичних методах / властивостях, якщо ви не хочете, щоб воно було дійсно глобальним.

Слово обережності # 3

Загалом ви хочете використовувати те, що називається Late-Static-Binding, використовуючи static замість self. Але зауважте, що вони не однакові, так що кажуть "завжди користуйтеся" static замість self дійсно короткозорий. Замість цього зупинись і подумайте про дзвінок, який ви хочете зробити, і подумайте, якщо ви хочете, щоб дитячі класи мали можливість перевизначити це статичний вирішено дзвонити

TL / DR

Дуже погано, поверніться і прочитай. Це може бути занадто довгим, але це так довго, тому що це складна тема

TL / DR # 2

Добре, гаразд. Коротко, self використовується для посилання поточне ім'я класув класі, де як $this відноситься до поточного об'єкта екземпляр. Зауважте, що self це скопіювати / вставити скорочення. Ви можете спокійно замінити його ім'ям свого класу, і це буде добре. Але $this це динамічна змінна, яку неможливо визначити заздалегідь (і навіть не може бути вашим класом).

TL / DR # 3

Якщо використовується об'єкт-оператор (->), Тоді ти завжди Знаєте, що маєте справу з екземпляром. Якщо використовується оператор scope-resolution (::), вам потрібна додаткова інформація про контекст (чи є ми в об'єктному контексті? Чи ми поза об'єктом? і т. д.).


228
2018-06-10 15:21



Слово застереження № 1: $ це не буде визначено при виклику статичного методу: 3v4l.org/9kr0e - Mark Achée
Добре... $this не буде визначено, якщо ви дотримуєтеся "Суворих стандартів" і не називаєте методи статичними, які не визначені як статичні. Я бачу результат, який ви пояснили тут: 3v4l.org/WeHVM Погодьтеся, дуже дивно. - Mark Achée
Після повного прочитання довгого опису я відчував себе ледачим прокручувати вище, щоб переглянути його. Просто жартую, я спробував це: D. Спасибі, це дуже корисно. - Mr_Green
Було б приємно додати чітке пояснення про різницю між self :: $ властивістю та self :: властивістю; Я думаю, що це також досить заплутане - Tommaso Barbugli
WoC # 1 веде себе по-різному починаючи з PHP 7. Як Foo::isFoo() називається статичним $this не буде визначено. Це, на мій погляд, більш інтуїтивна поведінка. - Ще один інший результат дано якщо Bar повинні були пройти від Foo. Тоді дзвінок Foo::isFoo() насправді буде в межах контексту екземпляра (не специфічний для PHP7). - Kontrollfreak


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

Оскільки this це об'єкт, ви використовуєте його як: $this->member

Оскільки self це не об'єкт, він в основному тип, який автоматично відноситься до поточного класу, ви використовуєте його як: self::member


109
2017-09-30 07:26





$this-> використовується для позначення певного екземпляра змінних класу (змінних членів) або методів.

Example: 
$derek = new Person();

$ derek тепер є конкретним екземпляром Person. У кожної людини є first_name і last_name, але $ derek має певне ім'я first_name і last_name (Derek Martin). Усередині екземпляра $ derek ми можемо посилатися на такі як $ this-> first_name і $ this-> last_name

ClassName :: використовується для позначення цього типу класу, а також його статичних змінних, статичних методів. Якщо це допомагає, ви можете подумки замінити слово "статичний" на "спільним". Оскільки вони спільно використовуються, вони не можуть звертатися до $ this, який відноситься до певного екземпляра (не поділяють). Статистичні змінні (тобто статичні $ db_connection) можна розподілити між усіма екземплярами типу об'єкта. Наприклад, всі об'єкти бази даних поділяють одне з'єднання (статичне $ 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).

Статичні методи (наприклад, публічний статичний вид :: формат_телефонний_значок ($ цифр)) можуть бути використані без першого інстанцірування одного з цих об'єктів (тобто вони не відносяться до $ 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 (), це не проблема взагалі. Немає конфлікту Яй статичні методи!

SELF :: Якщо ви кодування назовні об'єкт, який має статичний метод, який ви хочете посилатися, ви повинні називати його, використовуючи ім'я об'єкта View :: format_phone_number ($ phone_number); Якщо ви кодування всередині ви можете, об'єкт, який має статичний метод, який ви хочете посилатися або використовуйте ім'я об'єкта View :: format_phone_number ($ pn), АБО ви можете використовувати ярлик self :: format_phone_number ($ pn)

Те саме стосується статичних змінних: Приклад: Перегляд :: templates_path проти self :: templates_path

Усередині класу БД, якщо ми мали на увазі статичний метод деякого іншого об'єкта, ми б використовували ім'я об'єкта: Приклад: Сесія :: getUsersOnline ();

Але якщо клас БД хотів послатися на власну статичну змінну, він просто сказав себе: Приклад: self :: connection;

Сподіваюся, це допомагає очистити речі :)


93
2017-10-22 17:52



У вас є $ ronny у вашому другому абзаці тексту, але, якщо я помиляюсь, це має бути $ derek. - James Skemp
Відмінна відповідь. Я просто хочу вказати, що, звертаючись до статичного атрибута, вам потрібно скористатись $ знак Наприклад self::$templates_path - henrywright


Від це повідомлення в блозі:

  • self відноситься до поточного класу
  • self може бути використаний для виклику статичних функцій та еталонних змінних для статичних елементів
  • self може використовуватися всередині статичних функцій
  • self також може вимкнути поліморфну ​​поведінку, обійшовши vtable
  • $this відноситься до поточного об'єкта
  • $this може використовуватися для виклику статичних функцій
  • $this не слід використовувати для виклику статичних змінних членів. Використовуйте self замість цього.
  • $this не можна використовувати всередині статичних функцій

27
2018-05-10 12:00





У PHP ви використовуєте власне ключове слово для доступу до статичних властивостей і методів.

Проблема в тому, що ви можете замінити $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() завжди буде виводити 'parent', while $this->who() буде залежати від того, який клас має об'єкт.

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

Отже, ви повинні використовувати себе лише тоді, коли $this не доступний, або якщо ви не хочете, щоб класи нащадків переписали поточний метод.


23
2017-12-29 13:20





Усередині визначення класу, $ це відноситься до поточного об'єкта, а сам відноситься до поточного класу.

Необхідно послатися на елемент класу, використовуючи сам, і посилатися на елемент об'єкта за допомогою $ this.

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

19
2018-05-08 06:58





Ось приклад коректного використання $ 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
2017-12-06 11:26