PHP 7添加了对anonymous classes的支持,但我似乎无法找到有关相关范围问题的任何信息。我知道我可以使用带有callables / closures的replace()
关键字来访问外部作用域变量(比如use
),有没有办法用匿名类做到这一点?
我希望能够在不依赖匿名类构造函数参数的情况下完成此操作,而无需在实例化之后添加setter方法或公共属性来存储值。
以下是一个例子:
function() use ($outer) { // do work with $outer }
答案 0 :(得分:9)
另一个解决方案可能是
$outer = 'something';
$instance = new class($outer) {
private $outer;
public function __construct($outer) {
$this->outer = $outer
}
public function testing() {
var_dump($this->outer);
}
};
答案 1 :(得分:2)
在这种情况下访问外部变量的唯一方法是使用$ _GLOBAL(我不推荐)。如果你不想使用构造函数或setter方法,我的建议是在匿名类中使用一个STATIC变量,并在属性之后将值设置为包含匿名类实例的变量(不能定义静态值)之前,因为班级是匿名的..)。这样做,你有一个更好的控制和一个静态变量,但在某种程度上这不是很平常,每当你创建一个新的匿名类时,实例和它的值属于接收“新对象”的VARIABLE,也许你可以更好地创建一个真正的类..但是请遵循一个带有静态值和匿名类的示例:
$i = new class {
public static $foo;
};
var_dump($i::$foo); //No value
$i::$foo = "Some value";
var_dump($i::$foo); //Has value
希望它有所帮助!
答案 2 :(得分:1)
http://php.net/manual/en/language.variables.scope.php
php变量范围文档中有一些说明。
此脚本不会产生任何输出,因为echo语句引用$ a变量的本地版本,并且未在此范围内为其分配值。您可能会注意到,这与C语言略有不同,因为C中的全局变量会自动提供给函数,除非被本地定义明确覆盖。这可能会导致一些问题,因为人们可能会无意中更改全局变量。在PHP中,如果要在函数中使用全局变量,则必须将其声明为全局变量。
在php中,类内部的方法可以访问的范围仅限于整个类的内部,并且不能被其他范围访问。因此,我认为您想要的效果不会在php中实现,至少在PHP GROUP决定更改PHP的默认行为之前。
当然,您仍然可以通过将变量声明为全局变量来使用它。
答案 3 :(得分:0)
即使OP确实声明他们希望避免使用public properties
和anonymous class constructor arguments
,但可接受的答案恰恰是,所以这里是一个使用公共财产的示例,可以通过使用私有财产和维护封装的二传手:
class Foo {
public function executionMethod() {
return "Internal Logic";
}
}
$foo = new Foo();
var_dump("Foo's execution method returns: " . $foo->executionMethod());
$bar = new class extends Foo {
public $barVal;
public function executionMethod() {
return $this->barVal;
}
};
$bar->barVal = "External Logic";
var_dump("Bar's execution method returns: " . $bar->executionMethod());
如果您无法覆盖继承的类的构造函数,那么我认为这很有用。
这将输出:
string(46) "Foo's execution method returns: Internal Logic"
string(46) "Bar's execution method returns: External Logic"
答案 4 :(得分:0)
如果您希望匿名类访问受保护或私有的外部属性和方法,则可以利用以下事实:闭包继承了其定义的作用域,并将它们绑定到一些魔术方法中以实现无缝连接行为。
这是未经测试的,但我很确定它会起作用:
$class = new class {
/**
* @var \Closure
*/
public static $outerScopeCall;
/**
* @var \Closure
*/
public static $outerScopeGet;
/**
* @param string $name
* @param array $arguments
* @return mixed
*/
public function __call(string $name, array $arguments = [])
{
$closure = static::$outerScopeCall;
return $closure($name, $arguments);
}
/**
* @param string $name
* @param array $arguments
* @return mixed
*/
public function __get(string $name)
{
$closure = static::$outerScopeGet;
return $closure($name);
}
};
$class::$outerScopeCall = function (string $name, array $arguments = []) {
return $this->$name(...$arguments);
};
$class::$outerScopeGet = function (string $name) {
return $this->$name;
};
$call
闭包将可以从定义的位置(而不是在何处)访问$this
的定义