类方法中的 PHP 匿名函数隐藏类名(想使用 self 之类的东西来处理类名)

Posted

技术标签:

【中文标题】类方法中的 PHP 匿名函数隐藏类名(想使用 self 之类的东西来处理类名)【英文标题】:PHP anonymous function within class method hides class name (would like to use something like self to address the class name) 【发布时间】:2015-04-17 13:26:15 【问题描述】:

在下面的 php 代码中,一行代码已被注释掉(参见 cmets)并替换为下一行,目的是在不指定类名的情况下达到相同的效果。但是,我试图在我的代码中消除的显式类名对函数是隐藏的。如何在不像原始代码那样明确写下类名的情况下解决这个问题?

class EmbeddedTriplets 

  private $count;

  private $values;

  function __construct($value = 0, $count = 1) 

    $this->count = $count;

    $this->values = array($value, $value, $value);

  

  public function getEmbeddedOutput() 

    if ($this->count > 0) 

      $output = $this->values;

      $func = function($value) 

        //return new EmbeddedTriplets($value);
        // HERE INSTEAD OF THE LINE ABOVE I WOULD LIKE TO WRITE ACHIEVE THE SAME THING
        // BUT WITHOUT SPECIFYING THE CLASS NAME (SO THAT IF THE CLASS NAME CHANGES THEN
        // I WILL ONLY NEED TO CHANGE IT IN ONE PLACE IN THE CODE, i.e. next to the class keyword).
        return new self($value);

      ;

      for ($i = 0; $i < $this->count - 1; $i++) 

         $output = array_map($func, $output);

      

      return $output;

    

    return null;

  



$et = new EmbeddedTriplets(10, 3);
print_r($et->getEmbeddedOutput());

输出:

<br />
<b>Fatal error</b>:  Cannot access self:: when no class scope is active on line <b>25</b><br />

预期输出:

Array
(
    [0] => EmbeddedTriplets Object
        (
            [count:EmbeddedTriplets:private] => 1
            [values:EmbeddedTriplets:private] => Array
                (
                    [0] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                    [1] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                    [2] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                )

        )

    [1] => EmbeddedTriplets Object
        (
            [count:EmbeddedTriplets:private] => 1
            [values:EmbeddedTriplets:private] => Array
                (
                    [0] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                    [1] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                    [2] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                )

        )

    [2] => EmbeddedTriplets Object
        (
            [count:EmbeddedTriplets:private] => 1
            [values:EmbeddedTriplets:private] => Array
                (
                    [0] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                    [1] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                    [2] => EmbeddedTriplets Object
                        (
                            [count:EmbeddedTriplets:private] => 1
                            [values:EmbeddedTriplets:private] => Array
                                (
                                    [0] => 10
                                    [1] => 10
                                    [2] => 10
                                )

                        )

                )

        )

)

【问题讨论】:

【参考方案1】:

使用__CLASS__ 常量:

$class = __CLASS__;
return new $class($value);

从 PHP 5.5.0 开始,您可以使用 class:

$class = self::class;

据我所知,仍然没有单行。

【讨论】:

单线也可以做同样的事情吗? return new __CLASS__($value); 不起作用。有没有别的解决办法。如果可能的话,我不想创建那个额外的变量。谢谢。 我很确定没有,但也许其他人有想法。 让我们拭目以待。如果没有人提出任何建议,那么我会接受您的回答(如果 PHP 实现了一个等效于 call_user_func() 的名称为 new_instance() 或其他东西,那就太好了。谢谢。 似乎是一个语法问题(PHP 语法不允许我们想使用它的常量)。 不,因为一旦你在闭包中,你就超出了类范围(不再在类中)。 php 文件中的所有函数基本上都被“拉”到顶层。您必须将类存储在一个变量中并将其传入。另请注意,__CLASS__ 发生在编译时,self::class 发生在运行时。【参考方案2】:

并没有什么更好的解决方案(它实际上使用了更多的代码行),但它展示了如何也可以对此类函数进行编码以使用类实例:

class EmbeddedTriplets 

  private $count;

  private $values;

  private $class;

  function __construct($value = 0, $count = 1) 

    $this->count = $count;

    $this->values = array($value, $value, $value);

    $this->class = __CLASS__;

  

  public function getEmbeddedOutput() 

    if ($this->count > 0) 

      $output = $this->values;

      $class = $this->class;

      $func = function($value) use ($class) 

        return new $class($value);

      ;

      for ($i = 0; $i < $this->count - 1; $i++) 

         $output = array_map($func, $output);

      

      return $output;

    

    return null;

  



$et = new EmbeddedTriplets(10, 3);
print_r($et->getEmbeddedOutput());

【讨论】:

以上是关于类方法中的 PHP 匿名函数隐藏类名(想使用 self 之类的东西来处理类名)的主要内容,如果未能解决你的问题,请参考以下文章

匿名内部类

php 闭包:为啥绑定到静态类时匿名函数声明中的“静态”?

Xposed hook函数内有匿名内部类该怎么写

(10)静态方法静态字段静态类匿名类

深入类的方法。

java中关于内部类和匿名内部类