PHP 5.4 - "закрытие $этой поддержки"
Я вижу, что новыми запланированными функциями для PHP 5.4 являются: черты, разыменование массива, интерфейс JsonSerializable и что-то называемое "closure $this support
"
http://en.wikipedia.org/wiki/Php#Release_history
В то время как остальные либо сразу очищаются (JsonSerialiable, разыменование массива), либо я искал специфику (черты), я не уверен, что такое "закрытие $этой поддержки". Я неудачно искал его или нашел что-нибудь об этом на php.net
Кто-нибудь знает, что это должно быть?
Если бы я должен был догадаться, это означало бы что-то вроде этого:
$a = 10; $b = 'strrrring';
//'old' way, PHP 5.3.x
$myClosure = function($x) use($a,$b)
{
if (strlen($x) <= $a) return $x;
else return $b;
};
//'new' way with closure $this for PHP 5.4
$myNewClosure = function($x) use($a as $lengthCap,$b as $alternative)
{
if(strlen($x) <= $this->lengthCap)) return $x;
else
{
$this->lengthCap++; //lengthcap is incremented for next time around
return $this->alternative;
}
};
Значение (даже если этот пример тривиален) состоит в том, что в прошлом, как только замыкание строится, фиксированные переменные "use" фиксированы. С "закрытием $этой поддержки" они больше похожи на членов, с которыми вы можете столкнуться.
Звучит ли это правильно и/или близко и/или разумно? Кто-нибудь знает, что означает это "закрытие $этой поддержки"?
Ответы
Ответ 1
Это уже было запланировано для PHP 5.3, но
Для PHP 5.3 $эта поддержка Closures была удалена, потому что не удалось достичь консенсуса о том, как реализовать ее разумно. Этот RFC описывает возможные пути, которые можно использовать для реализации в следующей версии PHP.
Это действительно означает, что вы можете ссылаться на экземпляр объекта (живая демонстрация)
<?php
class A {
private $value = 1;
public function getClosure()
{
return function() { return $this->value; };
}
}
$a = new A;
$fn = $a->getClosure();
echo $fn(); // 1
Для обсуждения см. PHP Wiki
и для исторического интереса:
Ответ 2
Одна вещь, которую пропустил Гордон, - это перевязка $this
. Хотя то, что он описал, является поведением по умолчанию, его можно повторно связать.
Пример
class A {
public $foo = 'foo';
private $bar = 'bar';
public function getClosure() {
return function ($prop) {
return $this->$prop;
};
}
}
class B {
public $foo = 'baz';
private $bar = 'bazinga';
}
$a = new A();
$f = $a->getClosure();
var_dump($f('foo')); // prints foo
var_dump($f('bar')); // works! prints bar
$b = new B();
$f2 = $f->bindTo($b);
var_dump($f2('foo')); // prints baz
var_dump($f2('bar')); // error
$f3 = $f->bindTo($b, $b);
var_dump($f3('bar')); // works! prints bazinga
Метод экземпляров bindTo
(альтернативно использует статический Closure::bind
) вернет новое замыкание с $this
повторно привязанным к указанному значению. Объем задается путем передачи второго аргумента, это будет определять видимость частных и защищенных членов при доступе изнутри закрытия.
Ответ 3
Основываясь на ответе @Gordon, можно подражать некоторым хакерским аспектам закрытия - $this в PHP 5.3.
<?php
class A
{
public $value = 12;
public function getClosure()
{
$self = $this;
return function() use($self)
{
return $self->value;
};
}
}
$a = new A;
$fn = $a->getClosure();
echo $fn(); // 12
Ответ 4
Просто опираясь на другие ответы здесь, я думаю, что этот пример продемонстрирует, что возможно PHP 5.4 +:
<?php
class Mailer {
public $publicVar = 'Goodbye ';
protected $protectedVar = 'Josie ';
private $privateVar = 'I love CORNFLAKES';
public function mail($t, $closure) {
var_dump($t, $closure());
}
}
class SendsMail {
public $publicVar = 'Hello ';
protected $protectedVar = 'Martin ';
private $privateVar = 'I love EGGS';
public function aMailingMethod() {
$mailer = new Mailer();
$mailer->mail(
$this->publicVar . $this->protectedVar . $this->privateVar,
function() {
return $this->publicVar . $this->protectedVar . $this->privateVar;
}
);
}
}
$sendsMail = new SendsMail();
$sendsMail->aMailingMethod();
// prints:
// string(24) "Hello Martin I love EGGS"
// string(24) "Hello Martin I love EGGS"
см. https://eval.in/private/3183e0949dd2db