Одно правило большого пальца: спросите себя: «Имеет ли смысл называть этот метод, даже если объект Obj еще не создан?» Если это так, это определенно будет статичным.
Итак, в классе Car
у вас может быть метод double convertMpgToKpl(double mpg)
, который будет статичным, потому что можно было бы знать, к чему преобразуется 35mpg, даже если никто когда-либо строил Автомобиль. Но void setMileage(double mpg)
(который устанавливает эффективность одного конкретного автомобиля) не может быть статичным, так как немыслимо вызвать метод до того, как какой-либо автомобиль был сконструирован.
(Btw, обратное не всегда верно : иногда вы можете иметь метод, который включает в себя два объекта Car
и все еще хочет, чтобы он был статичным. Например Car theMoreEfficientOf( Car c1, Car c2 )
. Хотя это можно было бы преобразовать в нестатистическую версию, некоторые утверждают, что, поскольку нет «привилегированный» выбор того, какой автомобиль более важен, вы не должны заставлять вызывающего абонента выбирать один автомобиль как объект, на который вы будете ссылаться на этот метод. Однако эта ситуация составляет довольно небольшую часть всех статических методов.)
В PHP методы и свойства находятся в отдельном пространстве имен (у вас может быть метод и свойство с тем же именем), и независимо от того, используете ли вы свойство или метод, зависит от синтаксиса, который вы используете для этого.
$expr->something()
- вызов метода, поэтому PHP будет искать something
в списке методов класса.
$expr->something
- это выборка свойств, поэтому PHP будет искать something
в списке свойств класса.
$myInstance->lambda();
анализируется как вызов метода, поэтому PHP ищет метод с именем lambda
в вашем классе, но такого метода нет (следовательно, Ошибка при вызове undefined method ).
Итак, вы должны использовать синтаксис fetch property для извлечения лямбда, а затем вызвать его.
]($obj->lambda)()
: ($obj->lambda)();
В скобках убедитесь, что PHP анализирует ($obj->lambda)
как для получения свойства с именем lambda . Затем ()
вызывает результат извлечения свойства. ->lambda->__invoke()
: $myInstance = new MyClass();
$myInstance->lambda->__invoke();
__invoke
является одним из PHP магические методы . Когда объект реализует этот метод, он становится invokable: его можно вызвать с помощью синтаксиса $var()
. Анонимные функции - это экземпляры Closure
, которые реализуют __invoke
. $lambda = $myInstance->lambda;
$lambda();
call_user_func($myInstance->lambda);
call_user_func
может вызывать любые callable
, включая анонимные функции. __call
для переадресации вызовов на ваш лямбда: class MyClass
{
private $lambda;
public function __construct()
{
$this->lambda = function() {
echo "Hello world!\n";
};
}
public function __call($name, $args)
{
return call_user_func_array($this->$name, $args);
}
}
Теперь это работает: $myInstance = new MyClass();
$myInstance->lambda();
С PHP 5.4 вы можете даже сделать это по признаку: trait LambdasAsMethods
{
public function __call($name, $args)
{
return call_user_func_array($this->$name, $args);
}
}
class MyClass
{
use LambdasAsMethods;
private $lambda;
public function __construct()
{
$this->lambda = function() {
echo "Hello World!\n";
};
}
}
$myInstance = new MyClass();
$myInstance->lambda();
Вы также можете вызвать свою лямбда-функцию без каких-либо изменений в своем классе, используя ReflectionFunction.
$myInstance = new MyClass();
$lambda = new ReflectionFunction($myInstance->lambda);
$lambda->invoke();
или если вам нужно передать аргументы, то
$args = array('arg'=>'value');
$lambda->invokeArgs($args);
__invoke/()
vs.call_user_func
. – user 16 January 2012 в 00:37