【问题标题】:static variable in php closure defined within a private class methodphp闭包中的静态变量在私有类方法中定义
【发布时间】:2014-11-09 15:16:25
【问题描述】:

所以我重新写了这篇文章,希望能更清楚地了解我正在尝试的内容。在某些数据解析期间,接收到与 someCode(s) 关联的 someValue(s)。目的是捕获具有最低优先级的 someCode 的特定值,而与 someCode/someValue (s) 接收的顺序无关。阻止这个工作的问题是每次调用私有函数时都会创建闭包,因此 $precedenceOfCodeCaptured 的值总是重置为 null。如果我能保持关闭状态,那么事情可能会按预期进行。

private function Foo($particularValue, $someValue, $someCode) {

    switch ($someCode) {
        case:
            CODE1:
        case:
            CODE2:

            $c = function () use ($someCode, $someValue) {
                static $precedenceOfCodeCaptured = null;
                $precedenceArray = array(
                    CODE2 => 1,
                    CODE1 => 2
                );

                if ((is_null($someValue))) {//first time the case statement matched because $someValue==null
                    $precedenceOfCodeCaptured = $precedenceArray[$someCode];
                    $particularValue = someValue;
                } else if ($precedenceArray[$someCode] <= $precedenceOfCodeCaptured) {
                    $particularValue = someValue;
                }

            };

            $c();
            break;
            ...
    }

}//end of private method

【问题讨论】:

  • 你能在闭包之外声明静态并用use传递它吗?
  • 不,这似乎不起作用。

标签: php static closures


【解决方案1】:

每次调用 Foo 时,您都会创建一个新函数/闭包,因为您评估一个 function(),而这就是评估 function() 所做的!

如果您想让 Foo() 每次都返回相同的函数/闭包,只需评估一次。也许使用单例模式,您将在其中检查是否已经初始化了一些包含函数的更高范围的变量,如果没有则初始化它。

例如:

$c = null;

private function Foo(){

  if ($c == null) {
  $c = function() use ( $whatever){  
               static $x = 0;
               echo "x= $x";
               $x++; 
  ...
  };
}   

$c(); }//私有方法结束

(但请不要在您的实际代码中使用全局变量!)

【讨论】:

  • 我修改了我的示例以更清楚地说明我的意图。似乎您正在展示如何使用不理想的全局来完成它,并且同样 patarkk 建议了一种使用类级别静态的方法。最好的是,如果有一种方法可以像您所说的那样“每次都有相同的函数/闭包,它有自己的静态变量”。必须在类范围内定义静态意味着我必须有多个(每个 case 语句都有一个。
  • 看,function() {} 构造每次被调用时都会创建一个新的函数/闭包,故事结束。如果你想重用它来访问相同的函数范围变量,你必须只保留一个引用,而不是继续重新创建它。此外,如果您没有从代码中传递闭包,如果您只是创建并调用它,那绝对没有意义。普通的类方法将完全按照您的意愿行事。在成员字段中保留“最低优先级”值,根据需要进行更新。
  • 是的,我第一次明白闭包每次被调用时都会被创建。我也明白(甚至在尝试关闭之前)类方法会起作用。然而,关键是通过在调用它的地方正确定义函数来保持事情非常清晰,而不是拥有一堆必须搜索的类方法。我要补充一点,闭包甚至不能(使用)函数级别的静态函数似乎受到限制。
  • 我明白了。 PHP 为此支持嵌套函数 - 在封闭函数内部编写带有名称的 function() {} 块,作为语句而不是表达式。您从内部函数创建闭包的值仍然需要在适当的范围内,但是...
  • 我不明白“你从内部关闭的价值”。根据我之前的评论,我认为闭包的用途之一是将它们内联以使事情更清晰。与拥有类方法相比,这似乎是一个很好的用途。你不同意吗?
【解决方案2】:

试试这个:

static $x = 0;
private function Foo() {
  $c = function() use ( $whatever){  
    echo "x= $x";
    self::$x++;
   ...
  };
  $c();
}

【讨论】:

  • 它可以使类级别静态,但根据我的尝试,它并不是最干净的。我修改了上面的示例以添加详细信息。
  • 另请参阅我对 BadZen 的其他评论,因为您的建议似乎几乎相同。
【解决方案3】:
<?php

class example{
    private function foo(){
        static $_closure;
        if( ! $_closure ){
            $_closure = function(){
                static $_state;
                /*  . . .  */
            };
        }
        $_closure();
    }
}

请注意,闭包是静态的(它是在第一次使用时创建的,而不是再次创建),在闭包内保存状态的变量也是如此。

但是,正如其他答案中所述,这充其量是“毫无意义的”。 $_closure 应该是另一个类方法; $_state 应该是一个类属性(闭包、foo() 和类中都不需要静态的任何东西)。使用这样的闭包并不是“更干净”、更易读或性能更好(事实上,可能恰恰相反)。

如果你正在做类似的事情可能是有意义的:

  • 退回瓶盖以供其他地方使用
  • 在运行时动态创建函数(即,基于 foo() args)
  • 其他动态和有趣的东西

……但就目前而言,这完全是错误的方法。执行此操作的工具已经存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-22
    • 2014-03-05
    • 1970-01-01
    • 2020-03-10
    • 2014-04-01
    • 2016-06-08
    • 2021-12-29
    • 2018-03-20
    相关资源
    最近更新 更多