Как стать автором
Обновить

Рекурсия при помощи self

Время на прочтение5 мин
Количество просмотров1K
Интересные и порой необычные свойства скрывает от документирования пятая версия PHP. Языковая конструкция self по определению служит для работы со статическими методами и свойствами классов. Но ее можно использовать и не по назначению.

Объявляю себя ...


Многие сталкивались с проблемой переименования класса (Забываешь переименовать конструктор, но ошибки нету и все вроде работает, но как-то кривовато). Именно чтобы решить эту проблему в PHP5 ввели стандартное имя для конструкторов __construct
Эту проблему можно еще больше облегчить, если использовать self для объявления нового экземпляра класса. Например:
class Spadar_Core_Object
{
    /**
     * Одиночный экземпляр класса
     *
     * @staticvar Spadar_Core_Object
     */
    private static $oInstance;

    …

    /**
     * Получить одиночный экземпляр класса (шаблон проектирования singleton)
     *
     * return Spadar_Core_Object singleton instance
     */
    public static function getInstance()
    {
        if (!isset(self::$oInstance))
        {
            self::$oInstance = new self();
        }

        return self::$oInstance;
    }

    …

}


Теперь за имя класса волноваться не стоит. Однако в этом случае, особой пользы от такого объявления мы не получаем.
Дальше представим себя крутыми разработчиками крутой библиотеки. И теперь все классы, для которых мы хотим использовать единственный объект должны для этого будут наследоваться от Spadar_Core_Object. Немного модифицируем код класса:

class Spadar_Core_Object
{
    /**
     * Одиночные экземпляры классов наследников
     *
     * @staticvar array
     */
    private static $aInstances = array();

    …

    /**
     * Получить одиночный экземпляр класса-наследника (шаблон проектирования singleton)
     *
     * return Spadar_Core_Object singleton instance
     */
    public static function getInstance()
    {
        if (!isset(self::$aInstances[__CLASS__]))
        {
            self::$aInstances[__CLASS__] = new self();
        }

        return self::$aInstances[__CLASS__];
    }

    …

}


Есть и альтернативный вариант: вместо new self завести переменную $sClassName = __CLASS__; и объявить так: new $sClassName();

Проверка типа параметров


В PHP5 для параметров методов можно указывать тип. В том числе в качестве типа можно указывать self

class Spadar_Controller_Widget extends Spadar_Core_Object
{
    /**
     * Сыылки на дочерние виджеты
     *
     * var array
     */
    protected $aChildWidgets = array();
    …

    /**
     * Добавление дочернего элемента к Виджету
     *
     * param Spadar_Controller_Widget $oWidget новый дочерний элемент
     * return Spadar_Controller_Widget вызываемый объект для последующих операций
     */
    public function addChild(self $oWidget)
    {
        $this->aChildWidgets[] = $oWidget;

        return $this;
    }

    …

}


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

Это я или не я?


Возвращаемся к написанию гипер-библиотеки на PHP. Предположим, что в каком-то пакете информация хранится через серализацию. Для того, чтобы правильно с ней работать нам нужно проверить соответствует ли она заданному интерфейсу:

class Spadar_Core_Object
{
    …

    /**
     * Восстановление объекта
     *
     * param string $sInfo
     * return Spadar_Core_Object вызываемый объект для последующих операций
     */
    private function parseObject($sInfo)
    {
        $mInfo = $sInfo;
        $mInfo = @unserialize($sInfo);

        if ($mInfo instanceof self)
        {
            return $mInfo;
        }

        return $this;
    }

    …

}


О Константах...



Константы классов можно использовать не только привычным способом внутри тела методов, но и немного поизвращаться с ними:

class Spadar_Controller_Url extends Spadar_Core_Object
{
    const PARSE_PROTOCOL = 'scheme';
    const PARSE_HOST = 'host';
    …
    const BROWSER_ARG_PROTOCOL = self::PARSE_PROTOCOL;

    /**
     * Какой параметр достать из урла
     *
     * param string $sParam параметр для доставания из URLа
     * return string значение параметра
     */
    public function getParam($sParam = self::PARSE_HOST)
    {
        …
    }

    …

}

Нужно помнить:
  • К константам классов-родителей можно тоже обращаться по self
  • Лучше переводить в константы все известные строковые конструкции. При дебаге проекта их проще искать
  • Динамически создавать константы можно будет только в PHP6.


Теги:
Хабы:
Всего голосов 10: ↑10 и ↓0+10
Комментарии11

Публикации

Истории

Ближайшие события

Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург