ФорумПрограммированиеPHP для идиотов → Статические классы

Статические классы

  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 11 сентября 2009 г. 6:26, спустя 3 секунды

    чо?
    Manual. Classes and Objects (PHP 5)

    Static Keyword

    Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).

    Свойства класса — это «состояние» в твоей терминологии или нет?
    Я оставил фразу про то, что через объект этого класса свойства класса недоступны (пока не пришол 5.3) — не в этом ли твоя проблема? Проблематично смешивать статические объявления и объекты. Но этот топик про полностью статические классы.
    ιιlllιlllι унц-унц
  • Trej Gun

    Сообщения: 5299 Репутация: N Группа: в ухо

    Spritz 11 сентября 2009 г. 6:26, спустя 23 часа 59 минут 57 секунд

    да. но у тебя их нет. зачем тогда инстанс?
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 11 сентября 2009 г. 6:29, спустя 2 минуты 54 секунды

    У меня есть class properties :) слово instance обычно используется в контексте объекта. instance of class == object
    Вот объектов в моем тестовом фреймворке пок что нет. Поясни что ты имеешь в виду.
    ιιlllιlllι унц-унц
  • Trej Gun

    Сообщения: 5299 Репутация: N Группа: в ухо

    Spritz 11 сентября 2009 г. 6:30, спустя 1 минуту 17 секунд

    мне лень много писать
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 11 сентября 2009 г. 6:31, спустя 43 секунды

    рад был поболтать
    ιιlllιlllι унц-унц
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 11 сентября 2009 г. 23:28, спустя 16 часов 56 минут 48 секунд

    Есть еще ограничение: к статическим свойствам неприменим overloading (хаки __get и __set).
    Похоже это обстоятльство невозможно обойти. По крайней мер в PHP 5.2.

    Property overloading only works in object context. These magic methods will not be triggered in static context. Therefore these methods can not be declared static.

    для __call в PHP 5.3 появляется аналог __callStatic

    Лично я никогда не использовал magic words __get и __set. Для меня это МЕФ. А для кого-то это может быть важно. В замечательном фреймворке Yii через геттеры/сеттеры реализован механизм "behavior". Все компоненты Yii — наследники класса CComponent. А в нём описаны геттеры/сеттеры. Лучше один раз увидеть (на примере геттера):


    public function __get($name)
    {
    $getter='get'.$name;
    if(method_exists($this,$getter))
    return $this->$getter();
    else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
    {
    // duplicating getEventHandlers() here for performance
    $name=strtolower($name);
    if(!isset($this->_e[$name]))
    $this->_e[$name]=new CList;
    return $this->_e[$name];
    }
    else if(isset($this->_m[$name]))
    return $this->_m[$name];
    else
    throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
    array('{class}'=>get_class($this), '{property}'=>$name)));
    }

    Как видно из кода, кроме методов getXxx() будут вызываться ещё и события 'onXxx'. К компоненту можно прицепить обработчики событий:

    $component->onClicked=$callback;


    Событие сработает при обращении к свойству $clicked.
    Конечно это должно подтормаживать всю систему в целом, но красиво! Если эффективность не главное — почему бы нет. Если верить тестам от самих Yii, он не самый тормозной среди мега-фреймворков.

    Через полностью статичские классы в полном объеме такое не сделать. В своем Простом фреймворке на СК я делаю обработчики событий, только они вызываются явно, а не по факту чтения/записи свойств.
    ιιlllιlllι унц-унц
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 12 сентября 2009 г. 3:51, спустя 4 часа 23 минуты 34 секунды

    Я ОПИЗДОШЕН

    Начиная эту тему я был уверен, что вызовы статических методов быстрее вызовов методов объекта, причем значительно. Я об этом не раз читал. Например здесь:

    http://www.hm2k.com/posts/50-php-optimisation-tips-revisited "In OOP, if a method can be a static method, declare it static. Speed improvement is by a factor of 4.."
    http://ilia.ws/files/frankfurt_perf.pdf "When object properties and methods will only be accessed statically, be sure to declare them as static. Improved performance (50-75%)"

    Наконец я взялся самостоятельно потестировать скорость обращения к статическим методам в сравнении с обычными и объектными.
    Результат меня удивил. Не могу понять… обращение к простой функции я взял за 100%, скорости для объекта порядка 135%, а для класса 145%. То есть статика медленнее?  

    Может быть я неправильно составил тест? Или это в старых версиях выгоднее было static, а в 5.2+ выгоднее объект? Прошу меня проверить.
    1. test.zip (43)
    ιιlllιlllι унц-унц
  • Trej Gun

    Сообщения: 5299 Репутация: N Группа: в ухо

    Spritz 12 сентября 2009 г. 3:14, спустя 23 часа 22 минуты 44 секунды

    это связано с тем что все статически методы на этапе синтаксического разбора превращаются в функции.
    поэтому я и спрашивал тебя, какого ты их засовываешь в классы?
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 12 сентября 2009 г. 3:26, спустя 11 минут 35 секунд


    это связано с тем что все статически методы на этапе синтаксического разбора превращаются в функции.
    поэтому я и спрашивал тебя, какого ты их засовываешь в классы?

    было бы логично если БЫ превращались, но похоже, что нет.
    зачем я их засовываю — я тебе ответил. может уже почитаешь?
    ιιlllιlllι унц-унц
  • rider-sx

    Сообщения: 2706 Репутация: N Группа: Адекваты

    Spritz 12 сентября 2009 г. 3:31, спустя 5 минут 19 секунд

    5.3 0.1260(100%) 0.2150(171%) 0.3222(256%)
  • rider-sx

    Сообщения: 2706 Репутация: N Группа: Адекваты

    Spritz 12 сентября 2009 г. 3:37, спустя 6 минут 15 секунд

    поясните мне почему вы не ставите в конце скрипта ?> ??? Разве это не стандарт???
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 12 сентября 2009 г. 3:38, спустя 1 минуту 11 секунд

    незачем просто ?>

    этот тест на виндовом локалхосте и PHP 5.2.0 без кеша у меня примерно такие цифры как у ridex-sx дает.
    на шаред-хостинге под linux, PHP 5.2.6, eAcceletaror дает 100%, 135%, 145%

    странно всё это… все ошибались или тест кривой?
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 12 сентября 2009 г. 4:47, спустя 1 час 9 минут 1 секунду

    artoodetoo, попробуй при опкоде кешере каком нить
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 12 сентября 2009 г. 22:57, спустя 18 часов 9 минут 17 секунд

    да х* с ним. как-нибудь потом глубже покопаю. мне ещё роутер дописывать :)

    update:
    Конечно я не удержался и покопал ещё :) Новый тест во вложении. Цель — сравнить self|classname и this|objectname. Еще очевидно, что если тестируемые функции не будут ничего вычислять, то разница проявится сильнее — все тестируемое время это именно затраты на вызов.
    Вот типичные усреднённые результаты:

    N: 0.0263(100%) 0.0314(119%) 0.0326(124%)
    O: 0.0265(100%) 0.0307(116%) 0.0321(121%)
    S: 0.0254(100%) 0.0313(123%) 0.0271(107%)

    левая колонка - простая функция, вторая - объект, третья - класс
    Я протестировал вызовы из разных мест. По строкам: N - вызов из "глобального контекста", O - из метода объекта, S - из статического метода. Таким образом я смог использовать префиксы $this и self
    Видно что статический вызов получает заметное преимущество при self !
    Еще я попробовал call_user_func для статики - получил около 350%. Медленный мазафака! В цикл такое помещать нельзя.

    Для меня выводы такие:
    - Вне контекста нельзя сказать что «статические вызовы быстрее объектных», всё может быть наоборот.
    Правильнее сказать «self::, быстрее чем classname:: или $object-> или $this->».
    Кроме того, в общем случае без контекста непонятно насколько накладно создавать сам объект.
    - Важно не дробить классы слишком мелко. Тогда процент упоминаний self будет выше.
    1. test2.zip (37)
    ιιlllιlllι унц-унц
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 19 сентября 2009 г. 7:40, спустя 6 дней 8 часов 43 минуты

    Ещё кое-что об ограничениях. Статический класс на то и статический, что у него нет экземпляров-объектов. Значит мы всегда обращаемся к классу явно. Вызов методов через call_user_func это неказистый хак. Предположим у нас есть фрейморк на статических классах и то, что НАД ним — приложение.
    Возникла нужда перекрыть функциональность базового класса. Не придется ли нам править базовый класс фреймворка? Не обязательно!
    Все варианты кроме №4 предполагают наличие автолоадера классов.

    Вариант 1: В конфигурации описываем путь до нового класса. Класс имеет то же имя и НЕ УНАСЛЕДОВАН ОТ БАЗОВОГО. Автолоадер загрузит его вместо дефолтного системного.

    Вариант 2: Закладываем приоритеты — сначала файл с классом ищется в папках приложения и только потом в system. Новый класс НЕ МОЖЕТ НАСЛЕДОВАТЬ от системного.

    Вариант 3: Подсмотрено во фреймворке Kohana. В кохане базовые классы имеют суффикс _Core, а используются БЕЗ суффикса. Магия! Дело в том, что автолоадер на лету создает пустой class SomeClass extends SomeClass_Core {}. Автолоадер сработает только в том случае, если приложение не успело загрузить свой SomeClass. Теоретически новый SomeClass может наследовать от системного SomeClass_Core. Ужасно то, что трюк выполняется через eval() и будет выполняться много раз — каждый раз когда системный класс НЕперекрыт. И эти люди запрещают мне ковыряться в носу!

    Вариант 4: Полагаться на механизм хуков-ивентов. Если приложение зарегистрировало свой обработчик события onBeforeMethod и событие обработалось успешно, то больше ничего не делать. Задача сводится к обработке событий.

    Вобщем вариантов много и все эти техники применяются в свежих фреймворках, хотя они не на 100% статичские.
    ιιlllιlllι унц-унц

Пожалуйста, авторизуйтесь, чтобы написать комментарий!