Примечание: Я уплотнил эту статью в свою личность Wiki: http://wiki.chacha102.com/Lambda - Обладает
Я испытываю некоторые затруднения из-за функций стиля Лямбды в PHP.
Во-первых, это работает:
$foo = function(){ echo "bar"; }; $foo();
Во-вторых, это работает:
class Bar{ public function foo(){ echo "Bar"; }
В-третьих, Это работает:
$foo = new stdClass; $foo->bar = function(){ echo "bar"; }; $test = $foo->bar; $test();
Но, это не работает:
$foo = new stdClass; $foo->bar = function(){ echo "bar"; }; $foo->bar();
И, это не работает
class Bar{ public function foo(){ echo "Bar"; } $foo = new Bar; $foo->foo = function(){ echo "foo"; }; $foo->foo(); // echo's bar instead of Foo.
Мой Вопрос состоит в том Почему?, и как может я гарантировать что оба это:
$foo->bar = function(){ echo "test"; }; $foo->bar();
и это
$foo = new Bar; $foo->bar();
названы правильно? Дополнительные очки, если Вы можете указать на документацию, указывающую, почему эта проблема происходит.
Это интересный вопрос. Это работает:
$a = new stdClass;
$a->foo = function() { echo "bar"; };
$b = $a->foo;
$b(); // echos bars
но, как вы говорите, это не так:
$a = new stdClass;
$a->foo = function() { echo "bar"; };
$a->foo();
Если вы хотите получить объект, к которому можно динамически вызывать членов, попробуйте:
class A {
public function __call($func, $args) {
$f = $this->$func;
if (is_callable($f)) {
return call_user_func_array($f, $args);
}
}
}
$a = new A;
$a->foo = function() { echo "bar\n"; };
$a->foo2 = function($args) { print_r($args); };
$a->foo();
$a->foo2(array(1 => 2, 3 => 4));
но вы не можете заменить вызываемые методы таким образом, потому что __call()
вызываются только для методов, которые либо не существуют, либо недоступны (например, они приватны).
Вы не получите никакого повышения производительности ни для одного из них. Реальный вопрос в том, какой из них более полезен.
Для скалярных значений (Последовательности, ints и т.д.), которые определены один раз, никогда не должны изменяться и должны быть доступны по всему месту, следует использовать константу.
Если имеется какая-то сложная вложенная конфигурация, например:
$config->facebook->apikey = 'secret_key';
$config->facebook->url = 'http://www.facebook.com';
Можно использовать массив или API конфигурации, предоставленный одним из множества рамок ( Zend _ Config не является плохим)
-121--4631870-По существу, статические методы позволяют писать процедурный код на объектно-ориентированном языке. Она позволяет вызывать методы без необходимости создания объекта в первую очередь.
-121--936361- Функции и методы в PHP обрабатываются по-разному. Для добавления метода в класс можно использовать runkit _ method _ add ()
, но я не знаю способа добавления метода в экземпляр.
Интересный вопрос, хотя я не вижу причин, почему это должно работать:
class Bar{
public function foo(){
echo "Bar";
}
$foo = new Bar;
$foo->foo = function(){ echo "foo"; };
$foo->foo(); // echo's bar instead of Foo.
У меня была аналогичная проблема с __ invoke ()
, и я также не смог решить ее:
class base {
function __construct() {
$this->sub = new sub();
}
function __call($m, $a) {
}
}
class sub {
function __invoke($a) {
}
}
$b = new base();
$b->sub('test'); // should trigger base::__call('sub', 'test') or sub::__invoke('test')?
Решение? Никогда не используйте __, призывают ()
!: P
Ближе всего к этому можно было бы подойти, используя перегрузку __call
, чтобы проверить, содержит ли свойство закрытие:
class what {
function __call($name, $args) {
$f= $this->$name;
if ($f instanceof Closure) {
$f();
}
}
}
$foo = new what();
$foo->bar = function(){ echo "bar"; };
$foo->bar();
Хотя учтите следующее примечание из документов:
Анонимные функции в настоящее время реализованный с использованием класса Closure. Это деталь реализации и не стоит полагаться.
Reference: Anonymous functions
Мне это кажется ошибкой, а не «причудой»:
<?php
$t = new stdClass;
$t->a = function() { echo "123"; };
var_dump($t);
echo "<br><br>";
$x = (array)$t;
var_dump($x);
echo "<br><br>";
$x["a"]();
echo "<br><br>";
?>
object(stdClass)#1 (1) { ["a"]=> object(Closure)#2 (0) { } }
array(1) { ["a"]=> object(Closure)#2 (0) { } }
123
Он есть, я просто не думаю, что PHP умеет его запускать.
Подумайте вот о чем:
<?php
class A {
public $foo
public function foo() {
return 'The method foo';
}
}
$obj = new A;
$obj->foo = function() { return 'The closure foo'; };
var_dump($obj->foo());
Вы имеете в виду $obj->foo() закрытие или $obj->foo() метод? Это двусмысленно, и PHP принимает решение, что вы имеете в виду метод. Чтобы использовать закрытие, вы должны определить, что вы имеете в виду. Один из способов сделать это - использовать временную переменную, как это сделали вы. Другой способ - использовать call_user_func($obj->foo)
.
Я не знаю другого простого способа.