dongmen9517 2013-08-03 23:17
浏览 46
已采纳

用PHP设计噩梦

I've been trying for a long time now to find a correct design using PHP to achieve what I want, but everything I've tried failed and I'm guessing it's probably because I'm not looking from the right angle, so I wish some of you can enlighten me and give me some good advice!

The design might seem a little weird at first, but I assure you it's not because I like to make things complicated. For the sake of simplicity I'm only giving the minimal structure of my problem and not the actual code. It starts with these:

<?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()
    }
}

Class Mother_A defines a static method that uses constants and statics to be overridden by children. This allows to define a generic method (equivalent of a "template" method) in the derived class Mother_B. Neither Mother_A or Mother_B are intended to be instanciated, but Mother_B should not be abstract. This exploits Late Static Binding, which I find very useful btw.

Now comes my problem. I want to define two classes, in n distinct 'situations' (situation 1, situation 2, etc):

<?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
}

Of course I'm not actually giving these stupid names; both classes have different names in each situation, but both follow the same derivation pattern from Mother_A and Mother_B. However, in each individual case ('situation'), both classes need the exact same constants/static override, and I don't know how to do that without duplicating the override manually in both classes.


I tried many things, but the closest I got was to implement an interface Interface_Situation_k that defined constants and statics for the situation k, and make both children implement this interface. Of course, you can't define statics in an interface, so it failed, but you get the idea. I would have traded the interface for a class, but then there's no multiple inheritance in PHP, so it's not valid either. :/ I'm really stuck, and I can't wait to read a possible solution! Thanks in advance!

  • 写回答

1条回答 默认 最新

  • doutucui0133 2013-08-04 00:09
    关注

    this is the best i can do, i don't think there is a way to do it with less code. Look at the comments inside the code for more info.

    Fully working code:

    <?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 "
    ";
    Child_B_Situation_k::method_a();
    echo "
    ";
    Child_B_Situation_k::method_b();
    echo "
    ";
    echo '</pre>';
    ?>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥17 pro*C预编译“闪回查询”报错SCN不能识别
  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向