Не можете вызвать статический метод из класса как имя переменной?

Я использую php 5.2.6. У меня есть шаблон стратегии, а стратегии имеют статический метод. В классе, который фактически реализует одну из стратегий, он получает имя класса стратегии для создания экземпляра. Однако я хотел вызвать один из статических методов перед созданием экземпляра, например:

$strNameOfStrategyClass::staticMethod();

но это дает T_PAAMAYIM_NEKUDOTAYIM.

$> cat test.php

<?

interface strategyInterface {
        public function execute();
        public function getLog();
        public static function getFormatString();
}


class strategyA implements strategyInterface {
        public function execute() {}
        public function getLog() {}
        public static function getFormatString() {}
}

class strategyB implements strategyInterface {
        public function execute() {}
        public function getLog() {}
        public static function getFormatString() {}
}

class implementation {
        public function __construct( strategyInterface $strategy ) {
                $strFormat = $strategy::getFormatString();
        }
}

$objImplementation = & new implementation("strategyB") ;

$> php test.php

Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in /var/www/test.php on line 24

$> php -v

PHP 5.2.6-1+lenny9 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug  4 2010 03:25:57)

Будет ли это работать в 5.3?


person user151841    schedule 24.09.2010    source источник


Ответы (2)


Да. Этот синтаксис был представлен в версии 5.3.

В качестве обходного пути для ‹= 5.2 вы можете использовать call_user_func:

call_user_func(array($className, $funcName), $arg1, $arg2, $arg3);

or call_user_func_array:

call_user_func_array(array($className, $funcName), array($arg1, $arg2, $arg3));

Но с другой стороны, то, что вы пытаетесь сделать, на самом деле не имеет смысла...

Почему это статическая функция? Ваш конструктор в implementation все равно ожидает объект (это то, что ищет strategyInterface $strategy). Передача строки не будет работать, так как строки не реализуют интерфейсы. Итак, что бы я сделал, это сделать интерфейс нестатичным, а затем сделать что-то вроде:

$strategy = new StrategyB();
$implementation = new Implementation($strategy);

Затем в конструкторе:

$strFormat = $strategy->getFormatString();

Или, если вы действительно хотите, чтобы этот метод был статическим, вы можете сделать:

$strFormat = call_user_func(array(get_class($strategy), 'getFormatString'));

О, и = & new synax устарел (и не делает того, что вы думаете все равно делает).

person ircmaxell    schedule 24.09.2010
comment
У меня сегодня мозговой пердеж: P Я не хочу передавать созданный объект классу реализации, потому что я хочу создать его экземпляр в будущем, после того как класс реализации создаст некоторые данные, необходимые для стратегии. Думаю, мне все равно понадобится call_user_func_array() -- спасибо за отличный код! - person user151841; 24.09.2010
comment
Обратите внимание, что это работает только в версии 5.3. Вы можете использовать $foo::staticMethod(), но не $this-›foo = new Whatever(); $this-›foo::staticMethod(). - person ; 22.12.2012

Подсказка типа создаст вам некоторые проблемы:

Аргумент 1, переданный в реализацию::__construct(), должен реализовать интерфейс StrategyInterface, заданная строка

person Mark Baker    schedule 24.09.2010
comment
Хм, мозг пердит этим утром. Почему мой php не дал мне эту ошибку? - person user151841; 24.09.2010
comment
@ user151841 - Поскольку во время компиляции обнаруживается неожиданный T_PAAMAYIM_NEKUDOTAYIM, поэтому вы получали эту ошибку ... Я исправил это с помощью call_user_func() еще до того, как попытался запустить код, и получил вторую ошибку, которая является ошибкой времени выполнения. - person Mark Baker; 24.09.2010