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
)
);
}
}