2013-07-23 3 views
3

내가 아래 재생 스크립트에 도시 된 다음 클래스 계층 구조를 가지고 객체 :병합 배열 속성은

<?php 
header('Content-Type: text/plain'); 

class A 
    { 
     public $config = array(
      'param1' => 1, 
      'param2' => 2 
     ); 

     public function __construct(array $config = null){ 
      $this->config = (object)(empty($config) ? $this->config : array_merge($this->config, $config)); 
     } 
    } 

class B extends A 
    { 
     public $config = array(
      'param3' => 1 
     ); 

     public function __construct(array $config = null){ 
      parent::__construct($config); 

      // other actions 
     } 
    } 

$test = new B(); 

var_dump($test); 
?> 

출력 :

내가 원하는 무엇
object(B)#1 (1) { 
    ["config"]=> 
    object(stdClass)#2 (1) { 
    ["param3"]=> 
    int(1) 
    } 
} 

, A::$config가 오버라이드 (override)하지 않는 것이있다 에 의해 B::$config. B에서 자손 클래스가 많이있을 수 있습니다. 여기에서 $config을 변경하려고합니다. 그러나 $config 부모의 값과 병합/덮어 쓰려면이 값이 $config이어야합니다.

Q : 어떻게하면됩니까?

나는 array_merge()을 사용해 보았지만 비 정적 모드에서는 이러한 변수가 무시됩니다. static (늦은 정적 바인딩)없이 클래스 트리의 병합 효과를 얻을 수있는 방법이 있습니까?

+1

에서 적응 당신은 아마 * * 현재 클래스, 부모, 부모 등과 배열을 병합을 검토, Reflection'와 반성 '의 많은 것을 할 수 있습니다. http://php.net/reflectionclass를 참조하십시오. – deceze

+0

@deceze 답변을 작성하여 나중에 다른 사용자에게 유용 할 것입니다. :) –

+0

@deceze 음, 과열이 많이 발생합니까? – BlitZ

답변

3

당신은 당신의 확장 클래스가

class B extends A 
{ 
    private $defaults = array('param3' => 1); 
    public function __construct(array $config = null){ 
     parent::__construct($config?array_merge($this->defaults, $config):$this->defaults); 
    } 
} 
+0

그것을 재검토 해 보았습니다. 감사. – BlitZ

+0

또 다른 옵션으로'A'를 그대로 사용하고 싶다면'B'를'A' [decorator] (http://en.wikipedia.org/wiki/Decorator_pattern) – Orangepill

+0

@CORRUPT로 설정하면됩니다. 'public $ config'를'private $ defaults'로 바꿈으로써 그가 한 변화들. –

3

당신은 ReflectionClass를 사용하는 것을 할 수 인스턴스화하는 방법을 재구성 할 수 있습니다. $this을 introspect하여 시작하고 getProperty()을 사용한 다음 getParentClass()을 사용하여 부모 클래스와 그 부모 등에서 동일한 작업을 수행 한 다음 결과 배열을 병합하십시오.

이것은 아마도 이 아니며,인데, 문제가 발생했을 때 가장 좋은 해결책입니다.

+0

나는 그것을 좋아하지만 과열이 있습니다. 누군가가 그것을 알기를 바랍니다. 하지만 제 상황에는 없습니다. +1 – BlitZ

4

$config 속성을 생성자에서 변경할 값으로 선언하는 대신 이러한 값을 기본값으로 선언하는 것이 좋습니다. 이것은 또한 Orangepill의 답변에 설명되어 있습니다.

class A 
{ 
    public $config; 

    private $defaults = array(
     'param1' => 1, 
     'param2' => 2, 
    ); 

    public function __construct(array $config = array()) 
    { 
     $this->config = (object)($config + $this->defaults); 
    } 
} 

거기서 몇 가지 왜곡이 있습니다. $config 생성자 인수의 기본값을 빈 배열로 선언하면 위에 설명한 것처럼 array operators을 사용하여 코드를 단순화 할 수 있습니다. $config의 정의되지 않은 키는 $this->defaults으로 채워집니다.

확장 클래스는 매우 유사합니다

class B extends A 
{ 
    private $defaults = array(
     'param3' => 1 
    ); 

    public function __construct(array $config = array()) 
    { 
     parent::__construct($config + $this->defaults); 
    } 
} 
+0

너의 것이 더 예쁘다. – Orangepill

+0

@Orangepill 또한 정확하다. 나는 이것으로 끝내지 만,'$ defaults' 사례를 다시 생각해 보라고하셨습니다. – BlitZ

1

을 나는 다음 당신이 찾고있는 것을 믿습니다. Inherit static properties in subclass without redeclaration?

<?php 
class MyParent { 
    public static $config = array('a' => 1, 'b' => 2); 

    public static function getConfig() { 
     $ret = array(); 
     $c = get_called_class(); 
     do { 
      $ret = array_merge($c::$config, $ret); 
     } while(($c = get_parent_class($c)) !== false); 
     return $ret; 
    } 
} 

class MyChild extends MyParent { 
    public static $config = array('a' => 5, 'c' => 3, 'd' => 4); 
    public function myMethod($config) { 
     $config = array_merge(self::getConfig(), $config); 
    } 
} 

class SubChild extends MyChild { 
    public static $config = array('e' => 7); 
} 

var_export(MyChild::getConfig()); 
// result: array ('a' => 5, 'b' => 2, 'c' => 3, 'd' => 4,) 

$mc = new MyChild(); 
var_export($mc->myMethod(array('b' => 6))); 
// result: array ('a' => 5, 'b' => 6, 'c' => 3, 'd' => 4,) 

var_export(SubChild::getConfig()); 
// result: array ('a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 7,) 
+0

'static' 클래스와 같은 방식으로 작동합니다. 제 경우에는 비 정적 인 것이있었습니다. 그래도 작동 할 것입니다. 어쨌든 고마워. – BlitZ