2013-07-23 89 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不能被重写通过B::$config。可能有很多来自B的后代类别,我想要更改$config,但如果匹配$config值,则需要那些$config值合并/覆盖,如果匹配所有父代的$config值。

问:我该怎么做?

我试过使用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' [装饰器](http://en.wikipedia.org/wiki/Decorator_pattern) – Orangepill

+0

@CORRUPT它会工作,但看到通过将“public $ config”更改为“private $ defaults”所做的更改。 –

3

你可以做,使用ReflectionClass。通过内省$this开始,使用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

它对静态类的作用方式相同。在我的情况下,有非'静态'。尽管如此,它仍然有效。不管怎么说,还是要谢谢你。 – BlitZ