【问题标题】:How to inherit parent class array properties by merging array?如何通过合并数组继承父类数组属性?
【发布时间】:2013-01-03 06:05:02
【问题描述】:

我经常在我的类中使用存储一系列选项的属性。我希望能够以某种方式将这些选项与父类中声明的默认值合并。

我用一些代码演示了。

class A
{
    public $options = array('display'=>false,'name'=>'John');
}

class B extends A
{
    public $options = array('name'=>'Mathew');
}

现在,当我创建 B 时,我希望 $options 包含来自 A::options 的合并数组

现在发生的事情是这样的。

$b = new B();
print_r($b);
array('name'=>'Mathew');

我想要使用array_merge_recursive() 的类似功能。

array('display'=>false,'name'=>'Mathew');
  • 也许这是我可以在构造函数中做的事情?
  • 是否有可能使class A 成为一种行为?这样我就不必总是在所有子类中实现相同的代码。
  • 我可以使用反射在两个类中自动查找数组属性并将它们合并吗?

【问题讨论】:

    标签: php cakephp cakephp-2.2


    【解决方案1】:

    除了前面的答案之外,另一种可能适合某些情况的方法是使用 PHP 反射或内置类函数。这是使用后者的基本示例:

    class Organism
    {
        public $settings;
        public $defaults = [
            'living' => true,
            'neocortex' => false,
        ];
        public function __construct($options = [])
        {
            $class = get_called_class();
            while ($class = get_parent_class($class)) {
                $this->defaults += get_class_vars($class)['defaults'];
            }
            $this->settings = $options + $this->defaults;
        }
    }
    class Animal extends Organism
    {
        public $defaults = [
            'motile' => true,
        ];
    }
    class Mammal extends Animal
    {
        public $defaults = [
            'neocortex' => true,
        ];
    }
    
    $fish = new Animal();
    print_r($fish->settings); // motile: true, living: true, neocortex: false
    $human = new Mammal(['speech' => true]);
    print_r($human->settings); // motile: true, living: true, neocortex: true, speech: true
    

    【讨论】:

      【解决方案2】:

      我意识到我将您的接口从公共变量更改为方法,但也许它对您有用。请注意,如果您允许继续合并父操作,添加一个幼稚的 setOps($ops) 方法可能会出乎意料。

      class A
      {
          private $ops = array('display'=>false, 'name'=>'John');
          public function getops() { return $this->ops; }
      }
      class B extends A
      {
          private $ops = array('name'=>'Mathew');
          public function getops() { return array_merge(parent::getOps(), $this->ops); }
      }
      class c extends B
      {
          private $ops = array('c'=>'c');
          public function getops() { return array_merge(parent::getOps(), $this->ops); }
      }
      
      $c = new C();
      print_r($c->getops());
      

      出来:

      Array
      (
          [display] => 
          [name] => Mathew
          [c] => c
      )
      

      【讨论】:

      • 这也是个好主意。这将有助于避免 PHP 5.3 中的一些严格警告
      • $ops 设为私有会消除访问父级的 $ops 属性或覆盖它的可能性。它还强制在每次您想读取任何属性时调用父 getops 函数,而不是在实例化时调用一次 - 我不会说这是一个好的实现。 Matthew - 严格警告 =)?
      • 如果父级使用 __get 但父级没有将 $options 声明为属性,有时我会收到有关 $b->options 的警告。我喜欢你的方法。这是一个更经典的 OOP 设计,我将 getOps 放入一个接口中,使其更正式一点。
      • 这并没有直接回答问题,因为他想将child从parent中合并到parent中,这样就避免了将merge的责任放到每个子类中。
      • 我更喜欢@synexis 的回答。这个需要太多的手动编码。
      【解决方案3】:

      你可以像这样使用一个简单的模式:

      abstract class Parent {
      
          protected $_settings = array();
      
          protected $_defaultSettings = array(
              'foo' => 'bar'
          );
      
          public __construct($settings = array()) {
              $this->_settings = $settings + $this->_defaultSettings;
          }
      
      }
      

      通过这种方式,可以轻松地修改子类中应用的默认值:

      class Child extends Parent {
      
          protected $_defaultSettings = array(
              'something' => 'different';
          );
      
      }
      

      或者应用更复杂的东西:

      class OtherChild extends Parent {
      
          function __construct($settings = array()) {
              $this->_defaultSettings = Configure::read('OtherChild');
              return parent::__construct($settings);
          }
      
      }
      

      合并变量

      Cake 带有function for merging variables。它用于控制器属性,例如组件、帮助器等。但请小心将此函数应用于非平凡的数组 - 您可能会发现它并不能完全满足您的需求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多