2012-12-12 2 views
7

나는이처럼 보이는 PHP 코드가 있습니다

class A { 
    public function __construct() { 
     $this->b = new B(function($x) { return $x + 1; }); 
    } 
}; 

class B { 
    public function __construct($dataProcessingFunction) { 
     $this->dataProcessingFunction = $dataProcessingFunction; 
    } 

    public function processData($data) { 
     $f = $this->dataProcessingFunction; 
     return $f($data); 
    } 
}; 

을하지만 문제가 있습니다 : 나는 절대적으로 A의 소멸자 전에 호출하는 B의 소멸자가 필요합니다. 당신이 볼 수 있듯이 이것은 합리적인 것처럼 보입니다. B 객체에는 A가 필요하지 않으므로 아무런 문제가 없어야합니다.

그러나 PHP 5.4.0부터 클로저가 암시 적으로 $ this를 자동으로 캡처하는 것으로 보입니다. 따라서 B에 전달되고 B에 의해 저장되는 람다 함수는 A에 대한 참조를 포함합니다.

이는 A가 B에 대한 포인터를 포함하고 B에 A에 대한 포인터 (클로저를 통해)가 있음을 의미합니다. 이런 상황에서 PHP 문서에서는 소멸자가 가비지 콜렉션과 무작위 순서로만 호출된다고 말합니다. 그리고 B의 소멸자는 항상 A보다 먼저 호출됩니다.

우아한 방법으로 문제를 해결할 방법이 있습니까?

+0

:이 작업을 수행 할 수 없거나 구문 오류가 발생합니다

$cb = function($x) { return $x + 1; }; $cb = $cb->bindTo(null); // now $cb doesn't contain a pointer to $this anymore 

주 "~ 같다"- 분명히, anon func changelog에서 지적한 바와 같이 : http://php.net/manual/en/functions.anonymous.php –

+0

내가 생각할 수있는 가장 우아한 방법은 코드를 변경하는 것입니다. 소멸자 순서에 의존하지 않습니다. 이런 특정한 명령에 의지하면 곤경에 빠질 수 있습니다. – RonaldBarzell

+0

필자는 PHP 5.4가 없으므로 테스트 할 수는 없지만'create_function'을 사용해보십시오. 'Closure' 클래스를 사용하거나 함수가 바인딩 된 것을 변경할 수도 있습니다 (할당이 필요할만큼 익명이 아닌 것으로 생각합니다). –

답변

4

폭발성 알약 덕분에 Closure 클래스의 해결책을 찾았습니다.

당신은 실제로 $this이 같은 폐쇄 내부에 저장된 변경할 수 있습니다

// syntax error 
$cb = (function($x) { return $x + 1; })->bindTo(null); 
+0

D' oh .. 그건 내 담당자 야! –

+0

너를 풀다. –

관련 문제