-3

我已经尝试了很长时间来使用 PHP 找到正确的设计来实现我想要的,但是我尝试过的一切都失败了,我猜这可能是因为我没有从正确的角度看,所以我希望你们中的一些人能启发我并给我一些好的建议!

这个设计起初可能看起来有点奇怪,但我向你保证这不是因为我喜欢把事情复杂化。为了简单起见,我只给出问题的最小结构,而不是实际代码。它从这些开始:

<?php

// ------------------------------------------------------------------------

class Mother_A
{
    const _override_1 = 'default';
    protected static $_override_2 = array();

    public static function method_a()
    {
        $c = get_called_class();
        // Uses $c::_override_1 and $c::$_override_2
    }
}

// ------------------------------------------------------------------------

class Mother_B extends Mother_A
{
    public function method_b()
    {
        // Uses self::method_a()
    }
}

Mother_A定义了一个静态方法,该方法使用常量和静态值被子级覆盖。这允许在派生类中定义通用方法(相当于“模板”方法)Mother_B。既不也不Mother_A打算Mother_B被实例化,但Mother_B不应该是抽象的。这利用了后期静态绑定,顺便说一句,我发现它非常有用。

现在我的问题来了。我想在 n 个不同的“情况”(情况 1、情况 2 等)中定义两个类:

<?php 

// ------------------------------------------------------------------------

class Child_A_Situation_k extends Mother_A
{
    // Uses method_a
}

// ------------------------------------------------------------------------

class Child_B_Situation_k extends Mother_B
{
    // Uses method_a and method_b
}

当然,我实际上并没有给出这些愚蠢的名字;这两个类在每种情况下都有不同的名称,但都遵循从Mother_A和的相同派生模式Mother_B。但是,在每种情况下(“情况”),两个类都需要完全相同的常量/静态覆盖,如果不在两个类中手动复制覆盖,我不知道如何做到这一点。


我尝试了很多东西,但我得到的最接近的是实现一个Interface_Situation_k为情况 k 定义常量和静态的接口,并让两个孩子都实现这个接口。当然,你不能在接口中定义静态,所以它失败了,但你明白了。我会用接口换一个类,但是 PHP 中没有多重继承,所以它也无效。:/我真的被困住了,我迫不及待地想阅读一个可能的解决方案!提前致谢!

4

1 回答 1

1

这是我能做的最好的事情,我认为没有办法用更少的代码来做到这一点。查看代码中的注释以获取更多信息。

完整的工作代码:

<?php

class Mother_A
{
    // you're using '_override_1' as a variable, so its obviously not a constant
    // also i made it public for the setSituation function, 
    // you could keep it protected and use reflections to set it
    // but i dont really see a reason for that. 
    // if you want that, look up how to set private/protected variables
    public static $_override_1 = 'default'; 
    public static $_override_2 = array();

    public static function method_a()
    {
        $c = get_called_class();
        var_dump($c::$_override_1);
        var_dump($c::$_override_2);
        // Uses $c::_override_1 and $c::$_override_2
    }

    public static function setSituation($className)
    {
        $c = get_called_class();
        // iterate through the static properties of $className and $c 
        // and when the you find properties with the same name, set them
        $rBase = new ReflectionClass($c);
        $rSituation = new ReflectionClass($className);
        $staBase = $rBase->getStaticProperties();
        $staSituation = $rSituation->getStaticProperties();
        foreach($staSituation as $name => $value)
        {
            if(isset($staBase[$name])) $c::$$name = $value;
        }
    }
}

// ------------------------------------------------------------------------

class Mother_B extends Mother_A
{
    public function method_b()
    {
        self::method_a();
    }
}

class Situation_k
{
    public static $_override_1 = 'k';
    public static $_override_2 = array('k','k');
}

class Child_A_Situation_k extends Mother_A { }
Child_A_Situation_k::setSituation('Situation_k'); 
// This is not as short as writing 'extends Mother_A, Situation_k'
// but i think you wont get it shorter

class Child_B_Situation_k extends Mother_B { }
Child_B_Situation_k::setSituation('Situation_k');

echo '<pre>';
Child_A_Situation_k::method_a();
echo "\n";
Child_B_Situation_k::method_a();
echo "\n";
Child_B_Situation_k::method_b();
echo "\n";
echo '</pre>';
?>
于 2013-08-04T00:09:42.490 回答