从静态方法获取父类数据

时间:2014-07-18 10:18:15

标签: php oop php-5.2

在现有代码库中,我有一个返回实例的静态构建器方法。这是一个简化的例子:

class Grandparent{
}

class Parent extends Grandparent{
}

class Child extends Parent{
    public static fetchChildById($id){
        // ...
        return new Child;
    }
}

在实际代码中,我有一个Grandparent类和几个类似于ParentChild的子类(不只是ParentChild)。

我现在需要在Grandparent实施一个新方法,以便在fetchChildById()使用。这种方法需要利用同一父母的所有孩子共有的某些数据。由于我没有类实例,但我不得不将所有内容都设置为静态,但当然,由于无法覆盖静态属性和方法,因此无法正常工作:

class Grandparent{
    protected static $data = array(
        'default',
    );

    protected static function filter(){
        foreach(self::$data as $i){ // <!-- Will always be `default'
            // ...
        }
    }
}

class Parent extends Grandparent{
    protected static $data = array(
        'one',
        'two',
    );
}

class Child extends Parent{
    public static fetchChildById($id){
        self::filter();
        // ...
        return new Child;
    }
}

我认为这是后期静态绑定的一个用例,但代码需要在PHP / 5.2.0上运行:(

我不太喜欢我曾经想过的明显的解决方法:

  • 创建一个单独的构建器类建议在此时进行更多的重构:

    $builder = new ChildBuilder;
    $bart = $builder->fetchChildById(1);
    
  • 创建其他实例看起来很丑陋(也暗示了许多更改):

    $builder = new Child;
    $bart = $builder->fetchChildById(1);
    
  • 全局变量......哦,我还没那么绝望。

我是否忽略了一些明确的机制来自定义$data

1 个答案:

答案 0 :(得分:1)

这是使用反射的另一种选择。它需要修改所有fetchChildById实现,但它足以完成全局查找/替换:

self::filter(__CLASS__); // this is the modification

然后filter将成为:

protected static function filter($className){
    $reflect = new ReflectionClass($className);
    $data = $reflect->getStaticPropertyValue('data');
    foreach($data as $i){
        // ...
    }
}

更新:属性$data需要公开才能使上述工作正常工作(道歉 - 我在探索期间写了public)。但是,这是一个没有这个要求的同等版本:

$reflect = new ReflectionProperty($className, 'data');
$reflect->setAccessible(true);
$data = $reflect->getValue();