从类中定义一个闭包作为方法 [英] define a closure as method from class

查看:67
本文介绍了从类中定义一个闭包作为方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆