2010-06-23 2 views
0

나는 내가 가지고있는 문제에 대한 간단한 데모를 만들었습니다. 이것은 정확하게 구현하는 방법이 아니지만 같은 결과로 이어지는 것 같습니다.__get, __set 및 __unset을 사용하는 클래스의 예상치 못한 배열 내용

<?php 

class mainclass { 

    var $vardata = array(); 

    function &__get ($var) { 
     if ($this->vardata[$var]) return $this->vardata[$var]; 
     if ($var == 'foo') return $this->_loadFoo(); 
     return NULL; 
    } 

    function __set ($var, $val) { 
     $this->vardata[$var] = $val; 
    } 

    function __unset($var) { 
     unset($this->vardata[$var]); 
    } 

} 

class extender extends mainclass { 

    function __construct() { 

     var_dump($this->foo); 
     $this->_loadFoo(); 
     echo '<br>'; 
     var_dump($this->foo); 

    } 

    function _loadFoo() { 

     unset($this->foo); 
     $this->foo = array(); 

     $this->foo[] = 'apples'; 
     $this->foo[] = 'oranges'; 
     $this->foo[] = 'pears'; 

     return $this->foo; 

    } 

} 


$test = new extender; 

?> 

위의 코드의 출력은 다음과 같습니다

array(3) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" } 
array(5) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" [3]=> string(7) "oranges" [4]=> string(5) "pears" } 

내가 기대 한대로 여기서

array(3) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" } 
array(3) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" } 

__get, __set 및 __unset 기능은 모든 적절한 장소에서 호출되고있다 그래서 나는 두 번째로 직접 함수를 호출하여 $ this-> foo를 해제하고 같은 데이터로 다시 채울 것을 기대했을 것입니다. var_dumping을 사용하면 같은 결과가 나옵니다. 대신, 글쎄, 위의 작업을 끝내고 ... 3 개의 문자열 중 2 개의 문자열로 직접 채우고 처음 세 개의 원래 설정된 문자열을 유지합니다.

과부하 기능의 어리석은 실수 또는 오해. 어느 쪽이든, 나는 여기 오래 너무 오랫동안 여기에 갇혀 있었으므로 도움이 많이되었습니다! 많은 것들이 코드 문제가 있었다

답변

0

:

  • if ($this->vardata[$var])

    확인하는 방법이 아닌 변수가 존재입니다; isset 또는 (null이 허용되는 경우 array_key_exists)입니다.
  • mainclass에는없는 기능이 있습니다. 추상적이라고 선언 했어야합니다 (여전히 작동하지 않지만 메인 클래스를 인스턴스화하면 버그에 노출됩니다).
  • _loadFoo에 누락 된 배열 요소 (부수 효과 사용)를 설정하거나 foo 속성의 기본값을 반환하려는 경우에는 마음이 들지 않았습니다. __get에 참조로 돌아 왔으므로 반환 값이 아닌 실제 변수가 필요하다고 가정하고 첫 번째 경로로갔습니다. _loadFoo 두 가지 일을 모두했습니다 - 누락 된 배열 인덱스를 설정하고 값을 반환합니다. 배열 인덱스를 직접 설정하지 않은 것을 복잡하게하려면 오버로드에 의존해야합니다.

수정 버전 :

<?php 

abstract class mainclass { 

    var $vardata = array(); 

    function &__get ($var) { 
     if (isset($this->vardata[$var])) return $this->vardata[$var]; 
     if ($var == 'foo') { 
      $this->_loadFoo(); /* called for collaterals */ 
      return $this->foo; 
     } 
     return NULL; 
    } 

    abstract function _loadFoo(); 

    function __set ($var, $val) { 
     $this->vardata[$var] = $val; 
    } 

    function __unset($var) { 
     unset($this->vardata[$var]); 
    } 

} 

class extender extends mainclass { 

    function __construct() { 

     var_dump($this->foo); 
     $this->_loadFoo(); 
     echo '<br>'; 
     var_dump($this->foo); 

    } 

    function _loadFoo() { 

     unset($this->foo); 
     $this->foo = array(); 

     $this->foo[] = 'apples'; 
     $this->foo[] = 'oranges'; 
     $this->foo[] = 'pears'; 

    } 

} 

$test = new extender; 
+0

감사합니다. isset을 추가하면 그것을 구현 내에서 정렬합니다. 거기에는 약간의 감독이 있습니다. 지적 된 다른 문제는 제가 게시 한 샘플 코드에 대한 관련성있는 점입니다.이를 살펴볼 시간을내어 주셔서 감사합니다. – JoeR