Php,静态方法和继承.在寻找一个有效的模式


Php, static methods and inheritance.. in search of a valid pattern

实现这种行为的最佳模式是什么?

我有很多方法,比如method_1 ..method_N,它可以用一个参数来参数化,比如$k。我想把它们作为静态方法放在类中,所以我当然可以这样写我的compuationclass:

class Computation {
    static function method1( $k, $otherParams ) { ... }
    static function method2( $k, $otherParams ) { ... }
    static function method3( $k, $otherParams ) { ... }
}        

现在,因为$k属于一个特定的值范围,比如{'dog', 'cat', 'mouse'},我想创建计算的许多子类,每个可能的值一个。

class Computation_Dog extends Computation {
    static function method1( $otherParams ) { parent::method1('dog', $otherParams); }
    static function method2( $otherParams ) { parent::method2('dog', $otherParams); }
    static function method3( $otherParams ) { parent::method3('dog', $otherParams); }
}
class Computation_Cat extends Computation { .. }
class Computation_Mouse extends Computation { .. }

但是这很难看,让我放弃继承的优点:如果我在计算中添加一个方法会发生什么?必须编辑所有子类…然后我聪明地改成了:

abstract class Computation {
    abstract static function getK();
    static function method1($otherParams) { ... self::getK() .. }
    static function method2($otherParams) { ... self::getK() .. }
    static function method3($otherParams) { ... self::getK() .. }
}
class Computation_Dog extends Computation {
    static function getK() { return 'dog'; }
}

不错的尝试,但它不起作用,因为静态方法似乎不记住继承堆栈,并且self::getK()将调用Computation::getK()而不是Computation_Dog::getK()。

好. .希望足够清楚…你会如何设计这种行为?PS:我真的需要它们作为静态方法

谢谢

我根本不会设计这种行为。如果你需要调用parent::Method1('dog'),这意味着父类显然知道计算狗。你的Calculating_Dog类只是一个包含简写的愚蠢类。

是的,如果你在基类中添加一个方法,你就必须将它添加到所有其他类中。

如果您希望使用实例而不是静态类,则可以向包含计算类型的类添加属性。这样就不需要长函数了。您可以直接将速记函数添加到基类中,并使用属性而不是参数。你可以给这个类一个受保护的构造函数,并传递给它正确的类型。

然后,您可以创建具有不带参数的构造函数的后代,它们以所需类型作为参数调用父类构造函数。然后,对这些后代进行单例引用。

这是一种接近你想要的东西的方法。但我需要看到或听到你真正想要达到的目标,以确定这是否是最佳解决方案。

[编辑]

你可以使用__callStatic(来自PHP 5.3)来捕获不存在的方法的静态方法调用。然后,您可以将额外的'dog'参数移到属性的开头,并调用Calculate基类。这里演示了两种方法:

/* METHOD 1 Use __callStatic and make the parent function protected
   to hide them. Else __callStatic won't work. */
class Calculate1
{
    protected static function Method1($type, $param)
    {
        echo "Retrieving call for $type with param $param.";
    }
}
class Calculate_wrapper1 extends Calculate1
{
    static function __callStatic($functionName, $attributes)
    {
        array_unshift($attributes, 'dog');
        var_dump($attributes);
        // using get_parent_class()
        return call_user_func_array(array(get_parent_class(), $functionName), $attributes);
    }
}
Calculate_wrapper1::Method1('String');
/* METHOD 2 Don't inherit the wrapper from Calculate. This way the methods of
   Calculate itself can (must!) be public. */
class Calculate2
{
    public static function Method1($type, $param)
    {
        echo "Retrieving call for $type with param $param.";
    }
}
class Calculate_wrapper2
{
    static function __callStatic($functionName, $attributes)
    {
        array_unshift($attributes, 'dog');
        var_dump($attributes);
        // using the fixed class name
        return call_user_func_array(array('Calculate2', $functionName), $attributes);
    }
}
Calculate_wrapper2::Method1('String');

我不确定我完全理解代码,但我认为您的问题的解决方案是使用晚期静态绑定。

但是,如果你能更具体地说明这些方法到底是做什么的,我们也许能给你一个更好的整体解决方案。

从php5.3开始,你可以使用延迟静态绑定。用static::getK()代替self::getK()。后期静态绑定