程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP繼承方法獲取子類名講解

PHP繼承方法獲取子類名講解

編輯:關於PHP編程

看了一下datastore的入門,以及開始采用MVC方式來寫php,於是想拿php為redis寫個model,可以實現一些datastore的基本功能...於是碰到這樣一個問題-.-
php裡__CLASS__這類東西是靜態綁定的,如果不再子類裡重載的話,那麼繼承父類方法所得到的依舊是父類的名稱而不是子類的名稱。比如:
class A{
        function __construct(){
                echo __CLASS__;
        }
        static function name(){
                echo __CLASS__;
        }
}
class B extends A{}

此時無論將B實例化還是直接調用靜態方法,echo出來的都會是A。翻qeephp裡是用子類重載的方式解決這個問題,可是這樣的話沒新搞一個子類就得把相應調用類名的方法重載一邊.....這算是php在oop上的缺陷吧,試了試python上沒這個問題。
google之。找到兩個函數get_class()和get_called_class()。get_class()用於實例調用,加入參數 ($this)可解決子類繼承調用的問題,而get_called_class()則是用於靜態方法調用,可是...這玩意兒只在php 5.3以後才有....5.3還是比較遙遠的事...還好5.2之前可以手動實現這個函數:參閱http://php.net/manual/en /function.get-called-class.php 下方有高手添加了幾種5.3之前的實現方式。

if(!function_exists(get_called_class)) {
class class_tools
{
        private static $i = 0;
        private static $fl = null;
        public static function get_called_class()
        {
                $bt = debug_backtrace();
                //使用call_user_func或call_user_func_array函數調用類方法,處理如下
                if (array_key_exists(3, $bt) && array_key_exists(function, $bt[3]) && in_array($bt[3][function], array(call_user_func, call_user_func_array))
) {
                                //如果參數是數組
                                if (is_array($bt[3][args][0])) {
                                $toret = $bt[3][args][0][0];
                                return $toret;
                }else if(is_string($bt[3][args][0])) {//如果參數是字符串
                        //如果是字符串且字符串中包含::符號,則認為是正確的參數類型,計算並返回類名
                        if(false !== strpos($bt[3][args][0], ::)) {
                                $toret = explode(::, $bt[3][args][0]);
                                return $toret[0];
                        }
                }
        }
        //使用正常途徑調用類方法,如:A::make()
        if(self::$fl == $bt[2][file].$bt[2][line]) {
                self::$i ;
        } else {
                self::$i = 0;
                self::$fl = $bt[2][file].$bt[2][line];
        }
        $lines = file($bt[2][file]);
        preg_match_all(/([a-zA-Z0-9\_] )::.$bt[2][function]./,$lines[$bt[2][line]-1],$matches);
        return $matches[1][self::$i];
        }
        }
        function get_called_class()
        {
                return class_tools::get_called_class();
        }
}

於是現在可以把例子這麼修改:
class A{
        function __construct(){
                echo get_class($this);
        }
        static function name(){
                echo get_called_class();
        }
}
class B extends A{}
這樣就能讓B直接順利繼承獲取當前類名的方法了~

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved