【问题标题】:Design pattern for inheritable arrays?可继承数组的设计模式?
【发布时间】:2012-11-16 02:50:42
【问题描述】:

给定以下类结构:

class Foo {
    protected static $_things = ['thing'];
}

class Bar extends Foo {
    protected static $_things = [
        'thing', 'other-thing'
    ];
}

class Baz extends Bar {
    protected static $_things = [
        'thing', 'other-thing', 'something-else'
    ];
}

class Quux extends Baz {
    // Note the lack of "other-thing"
    protected static $_things = [
        'thing', 'something-else', 'one-more'
    ];
}

重构并保持数组元素更干燥的最佳方法是什么?例如,“thing”元素只能定义一次(Foo),“other-thing”元素只能定义一次(Bar),以此类推。

在实践中,这个数组非常大,有时可以有多达 4 或 5 级继承,每个都需要以某种特殊的方式“修改”这个数组,无论是添加 还是删除 元素。

我一直在玩弄可以进行适当修改的初始化方法的想法,但想先看看是否有更好的方法。

【问题讨论】:

    标签: php design-patterns inheritance


    【解决方案1】:

    我能想到的最简单的解决方案(主要基于单例模式)。

    我认为没有任何编译时方法可以完成您正在寻找的工作。

    <?php
    class A {
        private static $a = [1, 2, 3];
        public static function getA() {
            return self::$a;
        }
    }
    
    class B extends A {
        private static $a = null;
        public static function getA() {
            if (self::$a === null)
                self::$a = array_merge(A::getA(), [4, 5, 6]);
            return self::$a;
        }
    }
    
    echo join(',', B::getA()) . "\n";
    

    【讨论】:

    • 感谢您的建议。这实际上与我一直在玩弄的非常相似,只是我在构造函数而不是 getter 中进行合并。
    【解决方案2】:

    很难判断不完全了解用例,但继承似乎是错误的方法。 无论如何,您需要将数据的存储方式和访问方式分开,即将数据结构与数据模型分开。

    最好的解决方案是创建一个单独的列表类并在多个客户端中使用它。例如类似:

    class SomeList{
        private $_things = ['thing'];
        function mergeItems( $items ){
            //merge the $this->_things and $items arrays uniquely
            //...
        }
    }
    
    class Foo{
        private $list;
    
        function __construct( $list ){
            $this->list = $list;
            $this->list->mergeItems( ['thing', 'other-thing'] );
        }
    }
    

    你不应该将状态存储在静态属性中

    【讨论】:

    • 感谢您的回复,但该属性未存储状态。每个类都有一个用于该属性的可接受元素的常量/不可变数组。一旦它们被初始化,它们就永远不会改变。我遇到的问题是 1)PHP 没有任何方法来定义不可变数组,以及 2)我想保持数据 DRY。我目前只是覆盖每个类中的数组,并重复父类数组中的相关元素。这很好用,但维护起来很麻烦,因为修改基类中的一个元素也需要修改每个子类。
    • 如果数据是不可变的,那么您就更有理由封装数组并使其免受突变的影响。显然,如果这是您真正想要的,列表客户端可以静态存储列表实例。但是,您需要问自己是否真的需要它们是静态的。 (以及继承是否必要。继承很少保证。继承链几乎总是一种非常糟糕的代码味道)
    【解决方案3】:

    也许这样的事情会起作用:

    class Foo {
        protected static $_things = ['thing'];
    }
    
    class Bar extends Foo {
        protected static $_things = array_merge($_things, ['other-thing']);
    }
    
    //and so on...
    

    【讨论】:

    • 不,php 不允许在静态定义中使用除文字之外的任何其他内容(实际上,它甚至不会 PARSE 它)。
    猜你喜欢
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    相关资源
    最近更新 更多