【问题标题】:Php, static methods and inheritance.. in search of a valid patternPHP,静态方法和继承..寻找有效的模式
【发布时间】:2011-08-23 09:47:21
【问题描述】:

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

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

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

现在,由于 $k 属于特定范围的值,例如 {'dog', 'cat', 'mouse'},我想创建许多 Computation 子类,每个子类对应每个可能的值。

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 { .. }

但这很丑陋,让我放弃了继承的优势:如果我向 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:我真的需要它们作为静态方法

谢谢

【问题讨论】:

    标签: php inheritance static design-patterns


    【解决方案1】:

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

    是的,如果您将方法添加到基类,您必须将其添加到所有其他类。

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

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

    这将是一种接近你想要的方式。但我需要查看或听到您实际尝试实现的目标,以确定这是否是最佳解决方案。

    [编辑]

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

    /* 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');
    

    【讨论】:

    • 感谢您的回答。是的,你说的是真的.. 但是,正如我指定的,我需要静态方法.. 是的,Calculating_Dog 类只是一个包含包装器的愚蠢类.. 但这正是我想要的
    • 我使用 __callStatic 魔术方法添加了一个可能的解决方案。它允许您将所有静态函数调用重定向到类本身不存在的函数。这样,您不必将所有函数声明复制到所有包装类。
    【解决方案2】:

    我不确定我是否完全理解代码,但我认为您的问题的解决方案是使用Late Static Bindings

    但是,如果您可以更具体地了解这些方法的具体作用,我们或许可以为您提供更好的整体解决方案。

    【讨论】:

    • 谢谢。是的,后期静态绑定就是答案
    【解决方案3】:

    从 php5.3 开始,您可以使用后期静态绑定。使用 static::getK() 代替 self::getK()Late Static Bindings

    【讨论】:

    • 非常感谢,Late Static Bindings 正是我所需要的
    猜你喜欢
    • 2011-11-10
    • 2011-05-15
    • 2017-02-07
    • 2012-11-21
    • 2019-01-31
    • 2016-10-06
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多