Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 数组的静态继承_Php_Oop_Inheritance - Fatal编程技术网

Php 数组的静态继承

Php 数组的静态继承,php,oop,inheritance,Php,Oop,Inheritance,我很难解释我想做什么,所以我只举个例子 class A { static $data = ['a']; static function getData() { return static::$data; } } class B extends A { static $data = ['b']; } class C extends B { static $data = ['c']; } class D extends B { static $data

我很难解释我想做什么,所以我只举个例子

class A {
    static $data = ['a'];

    static function getData() { return static::$data; }
}

class B extends A {
    static $data = ['b'];
}

class C extends B {
    static $data = ['c'];
}

class D extends B {
    static $data = ['d'];
}

$a = new A;
$b = new B;
$c = new C;
$d = new D;

$a::getData(); // Output: Array('a'), Expected: Array('a');
$b::getData(); // Output: Array('b'), Expected: Array('a', 'b');
$c::getData(); // Output: Array('c'), Expected: Array('a', 'b', 'c');
$c::getData(); // Output: Array('d'), Expected: Array('a', 'b', 'd');
这可能吗


编辑:我有我的数据对象,每个对象都有一组属性规则。例如,一个用户对象有一个属性
名称
,它最多可以是10个符号,我在用户类的规则中定义了这一点,然后所有用户对象在其属性
名称
即将更改时都将遵守该规则。规则数组是静态的,因为它们应用于此类的所有对象。但是,当我在VIP用户中继承它时,VIP将需要为基本用户没有的属性设置附加规则。我需要能够扩展规则数组,但如果我在子类中定义这样的数组,它只会覆盖我也需要的父规则。

这将实现您想要的

class A {
    static $data = ['a'];

    static function getData() { return self::$data; }
}

class B extends A {
    static $data = ['b'];

    static function getData() { return array_merge(parent::getData(), self::$data); }
}

class C extends B {
    static $data = ['c'];

    static function getData() { return array_merge(parent::getData(), self::$data); }
}

class D extends B {
    static $data = ['d'];

    static function getData() { return array_merge(parent::getData(), self::$data); }
}

$a = new A;
$b = new B;
$c = new C;
$d = new D;

var_dump($a::getData()); // Array('a');
var_dump($b::getData()); // Array('a', 'b');
var_dump($c::getData()); // Array('a', 'b', 'c');
var_dump($d::getData()); // Array('a', 'b', 'd');


虽然可能有一种更简洁的方法,只在类a中定义getData(),但您希望合并数组,但在示例代码中从未指定此方法。调用
get\u parent\u class(get\u称为\u class())
获取父类,如果父类不存在,则为false

此外,如果要使用调用的实际类的值,则不能使用
self
,但必须使用
static
<代码>自身将始终使用相同的值

class A {
    static $data = ['a'];

    static function getData() {
        $parent = get_parent_class(get_called_class());
        if(method_exists($parent, 'getData')) {
            return array_merge($parent::getData(), static::$data);
        } else {
            return static::$data;
        }
    }
}
// other classes unchanged

因此,是的,有一种方法可以只使用父类方法来实现:

class A
{
    public static $data = ['a'];

    public static function getData()
    {
        $result = static::$data;
        $class  = get_called_class();
        while ($class = get_parent_class($class)) {
            $result = array_merge($result, $class::$data);
        }

        return $result;  
    }
}

class B extends A 
{
    public static $data = ['b']; 
}

class C extends B 
{
    public static $data = ['c']; 
}

class D extends C 
{
    public static $data = ['d']; 
}
演示

若顺序很重要,那个么更改合并参数的顺序(现在就像是在类层次结构链中一样——从子级到父级)

或,利用


演示。这条路甚至更短。因此,它可以通过普通数组映射来完成。不幸的是,当前类必须手动添加到迭代层次结构数组中。

您是否确实尝试了您想要尝试的内容?@D4V1D是的,但结果只是类声明时使用的元素。因此,请更精确地说明预期的内容和实际输出。@D4V1D已编辑,我希望现在更清楚。是否可能?对确实需要这样做吗?我怀疑。请解释一下你的情况。谢谢你的建议。我想我可以用一个特性来解决这个问题,但我仍然希望有一个更简单的解决方案:我想这是建议中最干净的解决方案。唯一让我感到不安的是,每次更改属性时都会运行,这意味着每次请求都会运行10秒。也许我可以想出一种方法,在第一次调用
getData()
时将合并的数组保存到子类中。
array\u merge()
从定义上讲是很慢的。这里有一个技巧:与其就地合并,不如将
$result
收集为元素,然后执行
返回call\u user\u func\u array('array\u merge',$result)
-相同的结果,只有一个合并。@AlmaDo我已经在执行方面简化了您的第二个建议,删除了两个函数调用和数组声明,因为OP似乎关心性能。也许把它缩小到一个简单的循环会进一步改进它,但我不是一个很内行的人,所以我不能肯定地说。
class A
{
    public static $data = ['a'];

    public static function getData()
    {
        $classes  = [get_called_class()]; //no class with name "0"
        $classes += class_parents($classes[0]);
        return call_user_func_array('array_merge', 
            array_map(
                function($class) {
                    return $class::$data;
                }, 
                $classes
            )
        );
    }
}