Перегрузка статических методов?

Тема в разделе "Как сделать...", создана пользователем PHP_Master, 24 сен 2008.

Статус темы:
Закрыта.
  1. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    Перегрузка динамических методов типа $class->foo()->method() реализуема.
    А возможно ли подобное, но только для статических методов (Class::foo(:(:method())?
    Перегрузка статических методов доступна в PHP 5.3, но описанный выше вариант у меня реализовать не получается.

    PS Просьба подсказки реализовать по типу синглтона не подсказывать :)


    Перебранки - личкой, на худой конец во флейме
     
  2. Liver

    Liver

    Регистр.:
    24 сен 2008
    Сообщения:
    316
    Симпатии:
    91
    Разве это перегрузка?

    Насколько я помню это разименование.
    Не знаю как там в 5.3, а в более ранних в принципе такое неосуществимо таким способом.

    :: используется для обращения либо внутри класса, либо должно быть известно имя класса (в версии 5.25 и ниже вбитое прямо в код).

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

    Сама необходиость появления такой конструкции должна трактоваться как сигнал к необходимости редизайна системы.
     
  3. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    Ещё один :p
    Объясняю популярно - поскольку PHP не является языком со строгой типизацией, перегрузка (в классическом значении этого термина) в нём не осуществима, в PHP перегрузкой называется возможность обращаться к необъявленным свойствам и методам класса.http://ru.php.net/language.oop5.overloading
    Ну имя класса полюбому должно быть известно :D Или есть некий сакраментальный способ создавать инстансы классов незная имени класа?
    "::" кроме адресации внутри класса, является способом доступа к статическим свойствам/методам класса без порождения его инстанса.
    call_user_func и reflection не имеют ни какого отношения к поднятому вопросу, а что лучше - я уж сам как-нибудь решу.
    Само появление подобного поста должно трактоваться как сигнал к необходимости подтянуть вам матчасть, а потом уж лезть в подобные топики.
    Если ты не знаешь для чего может быть полезна конструкция вида $class->foo()->method() и как её использовать, это значит всего лишь, что ты чего-то не знаешь :)

    Люди, умоляю, если ничего толково написать не можете, на форуме полно других топиков.
     
  4. Liver

    Liver

    Регистр.:
    24 сен 2008
    Сообщения:
    316
    Симпатии:
    91
    Значит хотим холливар? получайте.
    Вот именно. Вот это $class->foo()->method() типичный пример разименования. Телепатия не подсказала мне что method не существует. И для перегрузки надо было приводить такой пример: $class->method() и уточнить что вызов идет через __call
    Не надо мне цитировать мануал. Я вас первый туда ткнул. И прочитайте сами свои слова. А потом смотрите сюда.
    Class::foo(:(:method()
    Где у вас после вызова foo() известен класс?
    Эта задача неосуществима в версии 5.25 простым путем. Или криво, косо можно создать отдаленное подобие с лишним кодом через эти костыли. Можно. Но я уточнил, что не нужно.
    Ну ну. Я посмотрю найдется ли человек, который сможет решить то, что вы задумали.
    Эта конструкция так называемая fluent interface (если объект тот же) и также разименование. Эка невидаль. Использую крайне часто. И вы, видимо, хотите такое же к статике применить.
    Но это не является допустимым для php 5.25 (выше не знаю). Это заложено в синтаксис языка и кроме новой версии пхп (которая это поддерживает) решения нет.

    С таким же успехом можно пытаться сделать приватными методами в php4

    зы: интересно, почему сразу такое предвзятое отношение ко мне как к полному тупице в пхп? Из-за ника что ли?
    зы2: когда-нибудь вы попробуете TDD и ваше отношение к статическим методам изменится.
     
  5. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    Не-е-е, холивары мне не нужны :)
    Хотя иногда поспорить бывает полезно и поучительно.

    Разименование - это другое. Меня интересует, то что в пыхе называется перегрузкой вызова метода.
    ОК, попробую объяснить по другому.
    foo и есть имя класса: Class::NewClass(:(:methodOfNewClass(). Так понятнее?

    Я могу сделать
    PHP:
    $class = new Class;
    $class->NewClass()->methodOfNewClass();
    То есть через перегрузку вызова в инстансе $class я могу обратиться к методу другого класса (в нашем случае NewClass).
    Вопрос как сделать тоже самое, но со статическими классами.
    Ну я разве где-то указывал версию :p
    Наоборот, подчеркнул про 5.3.
    Тебе показалось.
    TDD и пользую. Статические методы мне не мешают.
     
  6. Liver

    Liver

    Регистр.:
    24 сен 2008
    Сообщения:
    316
    Симпатии:
    91
    Вот это уже нормальный разговор.

    Было замечание в стартовом топике, что в 5.3 это работает. Я его еще не пробовал. Мне нет смысла прыгать выше того, что стоит на сервере.

    Насколько я помню из мануала конструкция $class->NewClass() если метода нет вызовет __call. В нем можно сделать все что угодно. Главное вернуть обьект у которого и можно вызвать ->methodOfNewClass();

    Но дело в том, что экземпляр мы вернуть не можем, раз нам нужен статический метод, а возврат __CLASS__ "Class" ничего не дает. Так что даже поддержка вызова __call для статики ничего не даст.

    Более того пхп ругается еще на стадии редактора и выдает заумное название двоеточия при парсинге файла.

    Возможно в будущих версиях да, но пока это никак недостижимо.

    Хотя для себя я бы, если сильно захотел, мог использовать констркцию Class::foo()->method() с помощью реализации делегатов, дабы не нарушать возможные ограничения пхп.
    При этом все равно будет вызван статический метод. И цепочку можно продолжать бесконечно. Class::foo()->method()->bla()->сколько угодно. У меня есть мысль как реализовать.

    Устроит вас такой костыль?

    зы: А можно узнать по какой причине так необходимо использовать статики, а не объекты?
     
  7. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    Я рад что мы начали понимать друг друга.
    В 5.3 появился __callStatic, как раз для перегрузки вызова статических методов.
    У меня были подобные мысли. Но разве foo()->method() не потребует создание инстанса?
    Смысл моей затеи в том, чтоб не плодить инстансы там, где без них можно обойтись.

    С удовольствием посмотрю.

    PS может всё-таки на "ты"?
     
  8. Liver

    Liver

    Регистр.:
    24 сен 2008
    Сообщения:
    316
    Симпатии:
    91
    Потребует создание инстанса делегата.

    Но создание такого обьекта это же ерунда. Он выполняется мгновение. Там же почти нет функционала.
    Более того можно обойтись всего одним инстансом вспомив о паттерне "сборщик параметров", то есть создать 1 обьект делегата и передавая его использовать. Правда придется в сигнатуре статического метода объявлять дополнительный параметр.

    Вот он класс делегат. Я его украл из LIMB и сменил имена для своего проекта
    PHP:
    class LAF_Delegate
    {
      
    /**
      * @var mixed PHP callback
      */
      
    protected $php_callback;
      
    /**
       * @var bool cached validity check result
       */
      
    protected $is_valid;

      
    /**
      * Constructor.
      * @param mixed Object which method will be invoked
      * @param string Object method to call
      */
      
    function __construct($object$method null)
      {
        if(
    is_array($object))
        {
          
    $this->php_callback $object;
        }
        else
        {
          if(!
    $method)
            
    $this->php_callback $object;
          else
            
    $this->php_callback = array($object$method);
        }
      }

      
    /**
       * Returns PHP callback
       * @return mixed PHP callback
       */
      
    function getCallback()
      {
        return 
    $this->php_callback;
      }

      
    /**
      * Invokes object method with $args
      */
      
    function invoke()
      {
        if(!
    $this->isValid())
          throw new 
    LAF_Delegate_Exception("Invalid callback", array('callback' => $this->php_callback));

        
    $args func_get_args();
        return 
    call_user_func_array($this->php_callback$args);
      }

      function 
    invokeArray($args = array())
      {
        if(!
    $this->isValid())
          throw new 
    LAF_Delegate_Exception("Invalid callback", array('callback' => $this->php_callback));
        return 
    call_user_func_array($this->php_callback$args);
      }

      function 
    isValid()
      {
        if(
    $this->is_valid !== null)
          return 
    $this->is_valid;
        
    $this->is_valid is_callable($this->php_callback);
        return 
    $this->is_valid;
      }

      static function 
    objectify($delegate)
      {
        if(
    is_object($delegate) && $delegate instanceof LAF_Delegate)
          return 
    $delegate;
        return new 
    LAF_Delegate($delegate);
      }

      
    /**
      * Invokes all delegates in a list with some args
      * @param array Array of lmbDelegate objects that
      * @param array Invoke arguments
      */
      
    static function invokeAll($list$args = array())
      {
        foreach(
    $list as $item)
          
    $item->invokeArray($args);
      }

      
    /**
      * Invokes delegates in a list one by one. Stops invoking if delegate return a not null result.
      * @param array Array of lmbDelegate objects
      * @param array Invoke arguments
      */
      
    static function invokeChain($list$args = array())
      {
        foreach(
    $list as $item)
        {
          
    $result $item->invokeArray($args);
          if(!
    is_null($result))
            return 
    $result;
        }
      }
    }

    Это оригинальный класс. Вдруг пригодится.
    Можно изменить его так:

    Пускай в каждом статическом методе он создаётся и принимает в себя имя нового класса, но без метода и возвращается.
    В делегате нужно добавить новый метод
    PHP:
      function __call($name$args = array()){
    //тут уже устанавливаем нужный нам метод
    ...
    //и вызываем
         
    return $this->invokeArray(args);
    //вызывается статический метод и возвращается  новый делегат или можно передать этот и использовать дважды
      
    }
    То есть нужно переделать инициализацию метода да и всего делегата (сложный он больно) и поставить ___ перед всеми методами делегата, чтобы избежать наложения имен методов

    Примерно так. Щас ночь на дворе и пробовать уже сил нет.
     
    PHP_Master нравится это.
  9. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    Приблизительно так я и делаю сейчас, но блин так хочется чистой статики :ah: без шаманских плясок.
     
  10. Liver

    Liver

    Регистр.:
    24 сен 2008
    Сообщения:
    316
    Симпатии:
    91
    Без шаманских плясок - использовать обьекты.

    Я не вижу причин подобного использования статики, кроме минимизации количества обьектов.
    Но оно либо нерешаемо, либо решаемо через костыль с делегатами, а значит обьекты все равно создаются.
    И. наконец, почему нельзя их создавать? Даже 1000 обьектов это не нагрузка. И если не хочется возиться с "прокси", то отлично помогает отложенная инициализация.

    Ничто не мешает так разработке кода, как преждевременная оптимизация. От нее надо бежать как от чумы. Ранее, когда я продумывал все до мелочей, чтобы и быстро и гибко. И это мне вышло боком на 1000% времени увеличив разработку проекта. И в итоге я все равно его с нуля переписал но уже на TDD и не думая о скорости. А заказчик свзял помощнее сервер и оно все летает и так. Мне большой урок.
     
Статус темы:
Закрыта.