2013-07-23 139 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