douke1891 2011-02-23 00:56
浏览 30
已采纳

类的非显式扩展?

Scenario
The system has classes declared in /system/classes/.
The application has classes declared in /application/classes/.

If there is class in the application folder that has the same name as a class in the system folder then the class in the application folder should extend the class in the system folder.

Not all classes in the system folder will be overwritten by a class in the application folder.

Question
How can you cause the class in the system folder to extend the class in the application class only if there is a class in the application folder.

NB: All classes that can be overwritten are static classes
NB: Even if we have to name the application classes my_className it is fine, as long as we can still just call className::functionName()

I guess Im looking for something similar to how Code Igniter does it.


Edit

Example Class
The below class is used as a loader to load in all other classes (be they libraries, processes or other). It is also used to load in css/image/js files ect.

If the user was to extend the class they might want to add an ini() function which would be used to load in ini files.

class load {

    protected static $helpers;
    protected static $configs;
    protected static $libraries;
    protected static $processes;
    protected static $js;
    protected static $css;

    public static function init() {
        self::$helpers = new stdClass();
        self::$libraries = new stdClass();
        self::$configs = new stdClass();
        self::$processes = new stdClass();
        self::$css = new stdClass();
        self::$js = new stdClass();
    }

    public static function config($name) {
        if (isset(self::$configs->$name) && is_object(self::$configs->$name))
            return self::$configs->$name;

        if (is_file(CONFIG_DIR . $name . '.php')) {
            require_once(CONFIG_DIR . $name . '.php');
            self::$configs->$name = new $name();
            return self::$configs->$name;
        }
        throw new exception('Could not load config file \'' . $name . '\'');
        return false;
    }

    public static function helper($name) {
        if (isset(self::$helpers->$name) && is_object(self::$helpers->$name))
            return self::$helpers->$name;

        if (is_file(APP_HELPER_DIR . $name . '.php')) {
            require_once(APP_HELPER_DIR . $name . '.php');
            self::$helpers->$name = new $name();
            return self::$helpers->$name;
        }

        if (is_file(HELPER_DIR . $name . '.php')) {
            require_once(HELPER_DIR . $name . '.php');
            self::$helpers->$name = new $name();
            return self::$helpers->$name;
        }
        throw new exception('Could not load helper file \'' . $name . '\'');
        return false;
    }

    public static function library($name, $params = array()) {
        if (empty($params) && isset(self::$libraries->$name) && is_object(self::$libraries->$name))
            return self::$libraries->$name;

        if (is_file(APP_LIBRARY_DIR . $name . '.php')) {
            require_once(APP_LIBRARY_DIR . $name . '.php');
            self::$libraries->$name = new $name($params);
            return self::$libraries->$name;
        }

        if (is_file(LIBRARY_DIR . $name . '.php')) {
            require_once(LIBRARY_DIR . $name . '.php');
            self::$libraries->$name = new $name();
            return self::$libraries->$name;
        }
        throw new exception('Could not load library file \'' . $name . '\'');
        return false;
    }

    public static function process($name, $args = array()) {
        if (isset(self::$processes->$name) && is_object(self::$processes->$name))
            return self::$processes->$name;

        if (is_file(PROCESS_DIR . $name . '.php')) {
            require_once(PROCESS_DIR . $name . '.php');
            if (empty($args)) {
                self::$processes->$name = new $name();
                return self::$processes->$name;
            } else {
                self::$processes->$name = new ReflectionClass($name);
                return self::$processes->$name->newInstanceArgs($args);
            }
        }
        throw new exception('Could not load process file \'' . $name . '\'');
        return false;
    }

    public static function css($name) {
        if (isset(self::$css->$name) && !empty(self::$css->$name))
            return self::$css->$name;

        self::$css->$name = '<link rel="stylesheet" type="text/css" href="' . CSS_PATH . $name . '.css">';
        return self::$css->$name;
    }

    public static function js($name) {
        if (isset(self::$js->$name))
            return self::$js->$name;

        self::$js->$name = '<script src="' . JS_PATH . $name . '.js"></script>';
        return self::$js->$name;
    }

    public static function template($name, $vars = array()) {
        if (is_file(TEMPLATE_DIR . $name . '.php')) {
            ob_start();
            if (!empty($vars))
                extract($vars);
            require(TEMPLATE_DIR . $name . '.php');
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        }
        throw new exception('Could not load template file \'' . $name . '\'');
        return false;
    }

}
  • 写回答

1条回答 默认 最新

  • dongqin1861 2011-03-07 13:46
    关注

    As far as I know code Igniter do replace classes, rather than extending them.

    The more pratical way is to dinamically generate the code:

    $code = file_get_contents($appFile);
    if ( file_exists( $systemFile ) )
    {
        //don't do this ! Just a proof of concept, use regexp or code tokenizer
        //you will also need to programmatically determine MyClass and SystemClass
        $code = str_replace ('class myClass', 'class MyClass extends SystemClass', $code);
    }
    eval ($code)
    

    Please note that eval is generally considered evil for good reasons, so be sure to double check your code. You may want to re-think your framework design instead.

    UPDATE: if classes are just statical you may want to look into the Decorator pattern and __call() __get() __set(). That may suffice and avoid the eval() route.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)