Что делает new self (); имеете в виду в PHP?


110

Я никогда не видел такого кода:

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

Это то же самое, что и new className()?

РЕДАКТИРОВАТЬ

Если класс является наследственным, на какой класс он указывает?



@ stereofrog, ты имеешь в виду, что следует отказаться от одноэлементного шаблона? Но все существует по какой-то причине, верно?
user198729 07

О, я склонен согласиться с этим: синглтон следует заменить заводским
user198729 07

Синглтоны @stereofrog - яд для модульного тестирования, чрезвычайно сложно сделать неизменяемые тесты для чего-то, что меняет состояние от одного вызова к другому.
Дэвид

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

Ответы:


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, вы можете взглянуть на страницу Late Static Bindings в руководстве по PHP.


@Paul: heu ... означает "я действует как псевдоним" или "я как бы указывает на" - для этого можно использовать глагол "дизайнер" на французском языке - я полагаю, это одна из ситуаций в котором использование того же слова на английском языке не является хорошей идеей ;-( Я отредактирую свой ответ, чтобы исправить это ;; спасибо :-)
Паскаль МАРТИН

Что делать , если есть baseclass, class, что один он указывает на?
user198729 07

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

10

Похоже, это реализация паттерна Синглтон . Функция вызывается статически и проверяет, установлен ли в статическом классе переменная $_instance.

Если это не так, он инициализирует свой экземпляр ( new self()) и сохраняет его в $_instance.

Если вы вызовете, className::getInstance()вы получите один и тот же экземпляр класса при каждом вызове, что является точкой шаблона singleton.

Однако я никогда не видел, чтобы это делалось таким образом, и, честно говоря, не знал, что это возможно. Что $_instanceзаявлено как в классе?


1
$_instanceзаявлено какpublic static $_instance;
Atif

7

Это, скорее всего, используется в шаблоне проектирования singleton, в котором конструктор определен как частный, чтобы избежать создания экземпляра, (::)оператор двойного двоеточия может обращаться к членам, которые объявлены статическими внутри класса, поэтому, если есть статические члены, псевдопеременная $ это не может быть использовано, следовательно, вместо этого используется код self. Синглтоны - это хорошие методы программирования, которые допускают только 1 экземпляр объекта, например обработчики соединителей базы данных. Из клиентского кода доступ к этому экземпляру будет осуществляться путем создания единой точки доступа, в этом случае он назвал ее getInstance(), getInstance сама по себе была функцией, которая создала объект, в основном используя ключевое слово new для создания объекта, что означает, что метод конструктора был также называется.

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

private static $_instance = NULL; 

в обычных классах мы получили бы доступ к этому члену просто

$this->_instance = 'something';

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

self::$_instance

проверив, есть ли объект, хранящийся в этой статической переменной класса, класс может решить создавать или не создавать единственный экземпляр, поэтому, если он не установлен,! isset, что означает, что в статическом члене $ _instance нет объекта, тогда он генерирует новый объект, сохраняет его в статическом члене $_instanceкомандой

self::$_instance = new self();

и вернул его в клиентский код. Затем клиентский код может с радостью использовать единственный экземпляр объекта с его общедоступными методами, но в клиентском коде, вызывая единственную точку доступа, то есть getInstance()метод также сложен, его нужно вызывать следующим образом

$thisObject = className::getInstance();

причина, функция сама по себе объявлена ​​статической.


2

Да, это похоже на new className()(относится к классу, содержащему этот метод), вероятно, используется в шаблоне Singleton, где конструктор является частным.


Зачем кому-то использовать шаблон Singleton в PHP? Если он не используется в программе, подобной демону, синглтон будет существовать только во время выполнения скрипта, а затем исчезнет вместе с программой.
ILikeTacos

4
чтобы избежать раздражающего объявления global для доступа к глобальной переменной
Сэм Адамш

0

Если класс унаследован, то вызов getInstance () из дочернего элемента не даст вам экземпляр дочернего элемента. Он вернет только экземпляр родительского экземпляра. Это потому, что мы вызываем new self ().

Если вы хотите, чтобы дочерний класс возвращал экземпляр дочернего класса, используйте new static () в getInstance (), и затем он вернет экземпляр дочернего класса. Это называется поздним связыванием !!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.