Що робить нове Я (); означає в PHP?


110

Я ніколи не бачив такого коду:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

Це те саме, що new className()?

EDIT

Якщо клас є спадковим, на який клас він вказує?



@ stereofrog, ти маєш на увазі, що від однотонного шаблону слід відмовитися? Але все існує з причини, правда?
user198729

О, я схильний погоджуватися з цим пунктом: одиночку слід замінити на заводську
user198729

@stereofrog Singleton є отрутою для одиничного тестування, надзвичайно важко зробити непорушні тести на те, що змінює стан від одного дзвінка до іншого.
Девід

На жаль, цей метод не пошириться. Це завжди дасть вам новий об’єкт із класу, в якому була визначена ця функція.
Арес

Відповіді:


211

self вказує на клас, в якому він написаний.

Отже, якщо ваш метод getInstance в назві класу MyClass, наступний рядок:

self::$_instance = new self();

Зробимо так само, як:

self::$_instance = new MyClass();



Редагувати: ще кілька відомостей після коментарів.

Якщо у вас є два класи, які розширюють один одного, у вас є дві ситуації:

  • getInstance визначається у дочірньому класі
  • getInstance визначається у батьківському класі

Перша ситуація виглядала б так (я видалив увесь непотрібний код, для цього прикладу - вам доведеться додати його назад, щоб отримати одиночну поведінку) *:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Тут ви отримаєте:

object(MyChildClass)#1 (0) { } 

Що означає selfозначає MyChildClass- тобто клас, в якому він написаний.


У другій ситуації код виглядатиме так:

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

І ви отримаєте такий вихід:

object(MyParentClass)#1 (0) { }

Що означає selfозначає MyParentClass- тобто тут теж клас, в якому він написаний .




З PHP <5.3, що "клас, в який написано" є важливим - і іноді може викликати проблеми.

Ось чому PHP 5.3 вводить нове використання для staticключового слова: його тепер можна використовувати саме там, де ми використовувались selfу цих прикладах:

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Але, staticзамість цього self, ви отримаєте:

object(MyChildClass)#1 (0) { } 

Що означає, що staticтакий тип вказує на клас, який використовується (ми використовували MyChildClass::getInstance()), а не той, в якому він написаний.

Звичайно, поведінку selfне було змінено, щоб не порушити існуючі програми - PHP 5.3 просто додав нову поведінку, переробивши staticключове слово.


І, говорячи про PHP 5.3, ви можете поглянути на сторінку пізніх статичних прив’язок у посібнику PHP.


@Paul: heu ... означало, що "self виступає як псевдонім", або "self kind of points to" - дієслово "дизайнер", по-французьки, може бути використане для цього - я вважаю, це одна з ситуацій в якому використання того ж слова англійською мовою не є гарною ідеєю ;-( я відредагую свою відповідь, щоб виправити це ;; дякую :-)
Паскаль МАРТИН

Що робити, якщо є baseclass, на classякий він вказує?
user198729

@user: я відредагував свою відповідь, щоб дати трохи більше інформації про selfспадщину; і я також включив деяку інформацію про staticPHP 5.3 ;; сподіваюся, що це допомагає :-)
Паскаль МАРТИН

10

Це, здається, є реалізацією шаблону Сінглтона . Функція викликається статично і перевіряє, чи має статичний клас змінний $_instanceнабір.

Якщо це не так, він ініціалізує екземпляр себе ( new self()) і зберігає його в $_instance.

Якщо ви зателефонуєте, className::getInstance()ви отримаєте один і той же екземпляр класу при кожному виклику, що є точкою однотонної картини.

Я ніколи не бачив, щоб це робилося таким чином, і, чесно кажучи, не знав, що це можливо. Що $_instanceоголошено як у класі?


1
$_instanceоголошено якpublic static $_instance;
Atif

7

Це, швидше за все, використовується в однотонній схемі дизайну, де конструктор визначений як приватний, щоб уникнути інстанції, (::)оператор подвійної товстої кишки може отримати доступ до членів, оголошених статичними всередині класу, тому, якщо є статичні члени, псевдозмінна $ це не можна використовувати, отже, замість цього використовується код самостійно, Singletons - це хороша практика програмування, яка дозволить лише 1 екземпляр об'єкта, як обробники роз'ємів бази даних. З коду клієнта, доступ до цього екземпляра буде здійснюватися шляхом створення єдиної точки доступу, в цьому випадку він його назвав getInstance(), GetInstance сама по собі була функцією, яка створила об'єкт в основному за допомогою нового ключового слова для створення об'єкта, що означає метод конструктора. також називається.

рядок if(!isset(self::instance))перевіряє, чи об’єкт уже створений, ви не могли зрозуміти це, оскільки код - це лише фрагмент, десь у верхній частині повинні бути статичні члени, напевно

private static $_instance = NULL; 

в звичайних класах ми могли б отримати доступ до цього члена просто

$this->_instance = 'something';

але його оголошено статичним, і тому ми не могли використати $ цей код, який ми використовуємо замість цього

self::$_instance

перевіривши, чи є об'єкт, що зберігається в цій змінній статичного класу, потім клас може вирішити створити чи не створити один екземпляр, тому, якщо його не встановлено,! isset, тобто жоден об'єкт не існує на статичному члені $ _instance, то він генерує новий об'єкт, зберігаючи його в статичному члені $_instanceкомандою

self::$_instance = new self();

і повернув його до клієнтського коду. Потім клієнтський код може із задоволенням використовувати одиничний екземпляр об'єкта своїми загальнодоступними методами, але в коді клієнта, викликаючи єдину точку доступу, тобто getInstance()метод також складний, його потрібно викликати так

$thisObject = className::getInstance();

причина, функція сама по собі оголошується статичною.


2

Так, це як new className()(посилаючись на клас, що містить цей метод), ймовірно, використовується в шаблоні Singleton, де конструктор є приватним.


Чому хтось використовуватиме шаблон Singleton в PHP? Якщо не використовується в програмі, схожій на демон, сингл буде жити лише під час запуску сценарію, а потім зникне разом з програмою.
ILikeTacos

4
щоб уникнути роздратування, що заявляє про глобальний доступ до глобальної змінної
Сем Адамш

0

Якщо клас успадкований, то виклик getInstance () від дитини не надасть вам примірник дитини. Він поверне лише екземпляр батьківського екземпляра. Це тому, що ми називаємо нове «я» ().

Якщо ви хочете, щоб дочірній клас повернув екземпляр дочірнього класу, тоді використовуйте новий static () в getInstance () і він повертає дочірній екземпляр класу. Це називається пізнім зв'язуванням !!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.