从类中定义一个闭包作为方法 [英] define a closure as method from class
问题描述
我试图使用php5.3和闭包。
我看到这里(清单7.关闭一个对象: http://www.ibm.com/developerworks/opensource/library/os- php-5.3new2 / index.html ),可以在回调函数中使用$ this,但不是。所以我尝试给$作为使用变量:
$ self = $ this;
$ foo = function()use($ self){//使用$ self做某事}
所以使用同样的例子:
class Dog
{
private $ _name;
protected $ _color;
public function __construct($ name,$ color)
{
$ this-> _name = $ name;
$ this-> _color = $ color;
}
public function greet($ greeting)
{
$ self = $ this;
return function()use($ greeting,$ self){
echo$ greeting,I am a {$ self-> _color} dog named {$ self-> _name}。
};
}
}
$ dog = new Dog(Rover,red);
$ dog-> greet(Hello);
输出:
你好,我是一只名叫Rover的红狗。
首先这个例子不打印字符串但返回函数,但这不是我的问题。
其次,我无法访问private或protected,因为回调函数是一个全局函数,而不是来自Dog对象的上下文。这是我的问题。它是相同的:
函数greet($ greeting,$ object){
echo$ greeting,I am一个名为{$ self-> _name}的{$ self-> _color}狗。
}
我想要:
public function greet($ greeting){
echo$ greeting,I are a {$ self-> _color} dog named {$ self-> _name} 。;
}
这是来自Dog而不是全球。
那么,你不能使用$ this的全部原因是因为闭包是一个背景中的对象(Closure类)。
有两种方法。首先,添加__invoke方法(如果你调用$ obj()调用方法)。
class Dog {
public function __invoke($ method){
$ args = func_get_args();
array_shift($ args); //删除方法名
if(is_callable(array($ this,$ method))){
return call_user_func_array(array($ this,$ method),$ args);
} else {
throw new BadMethodCallException('Unknown method:'。$ method);
}
}
public function greet($ greeting){
$ self = $ this;
return function()use($ greeting,$ self){
$ self('do_greet',$ greeting);
};
}
protected function do_greet($ greeting){
echo$ greeting,I is a {$ this-> _color} dog named {$ this-> _name }。
}
}
如果您希望如果修改主机对象,你可以只改变返回函数为:
public function greet($ greeting){
$ self =(clone)$ this;
return function()use($ greeting,$ self){
$ self('do_greet',$ greeting);
};
}
另一个选项是提供一个通用的getter:
class Dog {
public function __get($ name){
return isset($ this-> $ name)? $ this-> $ name:null;
}
}
有关详细信息, a href =http://www.php.net/manual/en/language.oop5.magic.php =nofollow noreferrer> http://www.php.net/manual/en/language.oop5 .magic.php
i'm trying to play with php5.3 and closure.
I see here (Listing 7. Closure inside an object : http://www.ibm.com/developerworks/opensource/library/os-php-5.3new2/index.html) that it's possible to use $this in the callback function, but it's not. So I try to give $this as use variable :
$self = $this;
$foo = function() use($self) { //do something with $self }
So to use the same example :
class Dog
{
private $_name;
protected $_color;
public function __construct($name, $color)
{
$this->_name = $name;
$this->_color = $color;
}
public function greet($greeting)
{
$self = $this;
return function() use ($greeting, $self) {
echo "$greeting, I am a {$self->_color} dog named {$self->_name}.";
};
}
}
$dog = new Dog("Rover","red");
$dog->greet("Hello");
Output:
Hello, I am a red dog named Rover.
First of all this example does not print the string but return the function, but that's not my problem.
Secondly I can't access to private or protected, because the callback function is a global function and not in the context from the Dog object. Tha't my problem. It's the same as :
function greet($greeting, $object) {
echo "$greeting, I am a {$self->_color} dog named {$self->_name}.";
}
And I want :
public function greet($greeting) {
echo "$greeting, I am a {$self->_color} dog named {$self->_name}.";
}
Which is from Dog and not global.
Well, the whole reason that you can't use $this, is because the closure is an object in the background (the Closure class).
There are two ways around this. First, is add the __invoke method (What's called if you call $obj())..
class Dog {
public function __invoke($method) {
$args = func_get_args();
array_shift($args); //get rid of the method name
if (is_callable(array($this, $method))) {
return call_user_func_array(array($this, $method), $args);
} else {
throw new BadMethodCallException('Unknown method: '.$method);
}
}
public function greet($greeting) {
$self = $this;
return function() use ($greeting, $self) {
$self('do_greet', $greeting);
};
}
protected function do_greet($greeting) {
echo "$greeting, I am a {$this->_color} dog named {$this->_name}.";
}
}
If you want the closure to not change if you modify the host object, you can just change the return function to something like:
public function greet($greeting) {
$self = (clone) $this;
return function() use ($greeting, $self) {
$self('do_greet', $greeting);
};
}
The other option, is to provide a generic getter:
class Dog {
public function __get($name) {
return isset($this->$name) ? $this->$name : null;
}
}
For more information, see: http://www.php.net/manual/en/language.oop5.magic.php
这篇关于从类中定义一个闭包作为方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!