php靜態方法調用非靜態步驟不可取

來源:互聯網
上載者:User
php靜態方法調用非靜態方法不可取

那天對這個主題比較感興趣,於是就查了相關資料來記敘一下。不過,不知道自己寫的到底有沒有疏漏,所以,發到這裡來給大家當靶子。如果您發現有什麼敘述不正確的或不合理的,盡情拍磚——當然接受西紅柿和雞蛋。真理,只存在於辯論中。

---------------------------------------------
php中非靜態方法的靜態調用

參考資料:
1 Static method vs Non Static method?
http://bytes.com/topic/php/answers/495206-static-method-vs-non-static-method

2 PHP static method performance
http://vega.rd.no/articles/php-static-method-performance


php是個很詭異的語言。當然,這是對學習過C++或者Java等物件導向語言的人來說。
php可以定義靜態方法,然後通過className::staticMethod()形式來調用。非靜態方法,當然通過classObject->nonStaticMethod()使用。這個其他語言中也是如此,沒什麼大驚小怪的。可是,您能用className::nonStaticMethod()調用非靜態方法嗎?這方面恐怕Java和C++要冷汗直流了。其實,php自己也是滿臉黑線。為什麼這麼說呢?
先來看看物件導向的靜態和非靜態。物件導向的語言中,都會支援靜態方法。靜態方法,屬於類的固定資產的;非靜態方法,屬於類的執行個體的私人財產。在記憶體中,靜態方法,對於整個類也就只存了這麼一份;無論你new了多少個執行個體對象,它們共用的也就這麼一份。對於非靜態就不一樣了,你new幾個,記憶體就給你new幾份。另外,靜態方法內不可以調用非靜態方法,非靜態方法內卻可以調用靜態方法。這個就是靜態和非靜態區別。
物件導向用static關鍵字來定義靜態。未被標明是靜態方法,是不可以用類名加兩個冒號的形式調用的。php和其它很有區別的一點就是這個了:php中未被標明是靜態方法,也可以用類名加兩個冒號的形式調用。那麼為什麼php有這種文法?又為什麼感到很無奈呢?
-----以下說明php無奈的故事據相關資料改編,已經過演義處理--------
php之所以發展如此迅速,得益於它的速度。作為指令碼語言,php追求高速度和簡潔方便,所以選擇瞭解釋執行和使用過程方法。後來為了與國際接軌,引入了物件導向的概念。而就是在引入這個物件導向的特徵時,發生了一件令php目瞪口呆,最終無可奈何的事情。物件導向有個很重要的概念就是繼承。在繼承中,子類如果覆蓋父類的方法,同時需要調用父類的同名方法,該怎麼辦呢?php4版本提供了這樣一種方法:parentClassName::method()。提出此種方法之時,有識之士已經發現了問題:這個調用方式,不正是靜態方法的調用方式嗎?php4隨即答曰:不礙事。類中使用時,可以判斷此方式為子類正在調用父類方法;非類中使用時,就判斷為靜態調用了。所需要的只是發現此種調用時查詢一下方法映射就好了。其實,一想,也確實是那麼回事。php4後來想想,如果每次調用都檢驗一下此次調用是否合法,那多少也會影響效能,不如這個問題就交給程式員去控制吧:他們會知道只在類中使用此形式的調用的。唉,可惜天不遂人願。php4低估了程式員們的創造力!程式員們很快發現了這個方式,並且不餘遺力地使用起來。許多整合的API也開始使用這種怪癖的方式。php無奈了,隨即在php5中引入了另一種方式,使用關鍵字parent來調用父類函數:parent::method()。但是,想要放棄php的非靜態方法的靜態調用,著實是不再可能了。
--------------------
不過,話說回來,這種php的怪癖方式,有什麼好處嗎?效能和記憶體佔用方面如何呢?
於是我開始推理了:定義了一個非靜態方法,靜態調用時,php首先轉換此方法為靜態定義,載入入靜態記憶體地區,然後執行。通常一次業務,只使用一個業務處理類中的一個方法,如果使用非靜態定義,靜態調用,記憶體中豈不是只載入了這個業務類中的一個方法,不是就實現了靜態方法的按需載入嗎?豈不是要省下一部分記憶體?效能方面,無論是靜態調用,還是對象調用,反正都是執行一個方法,效能還不是一樣?並且靜態調用非靜態定義方法還省了一個new語句。嗯,嗯。這麼想的同時,手就開始寫上了。
那麼實際如何呢?我做了一個小測試。

PHP code

t::start();t::end(); //消除t類首次載入的影響t::start();model_profile_base::getBaseInfo($uid);t::end();t::start();$model = new model_profile_base();$model->getBaseInfo($uid);t::end();


model_profile_base是處理基本資料的一個業務類,比較複雜,比較接近於項目中的業務處理實際。
下面是用到的計時和統計記憶體的t類的定義:

PHP code

phpfunction microtime_float(){ list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec);}class t{ static $start_time; static $end_time; static $start_memory; static $end_memory; public static function start() { self::$start_memory = memory_get_usage(); self::$start_time = microtime_float(); echo '
Start @'.self::$start_time.'('.self::$start_memory.')|------->'; } public static function end() { self::$end_time = microtime_float(); self::$end_memory = memory_get_usage(); echo 'End @'.self::$end_time.'('.self::$end_memory.') :'; echo '|======= 共耗時:'.(self::$end_time-self::$start_time).',共用記憶體:'.(self::$end_memory-self::$start_memory); }}


這樣,只調用一次,結果如下:

PHP code

Start @1287561987.1805(1008368)|------->End @1287561987.1806(1008368) :|======= 共耗時:3.2901763916016E-5,共用記憶體:0Start @1287561987.1806(1008368)|------->End @1287561987.1938(1586452) :|======= 共耗時:0.013248920440674,共用記憶體:578084Start @1287561987.1938(1586452)|------->End @1287561987.1945(1586652) :|======= 共耗時:0.00065183639526367,共用記憶體:200


第二行是靜態調用非靜態方法,第三行是正常調用非靜態方法。然後,我發現我的推理悲劇了。刷了好幾次頁面,統計結果在數量級上都差不多。靜態調用非靜態方法無論記憶體佔用還是效能上都不敢恭維。這樣的結果有點令人咂舌。
那麼,再試一下迴圈執行多次的結果:

PHP code

t::start();t::end(); //消除t類首次載入的影響t::start();for($i=0; $i<1000;++$i) model_profile_base::getBaseInfo($uid);t::end();t::start();$model = new model_profile_base();for($i=0; $i<1000;++$i) $model->getBaseInfo($uid);t::end();



於是更讓人無語的結果出來了:

PHP code

Start @1287562243.5799(1009372)|------->End @1287562243.5799(1009372) :|======= 共耗時:3.0040740966797E-5,共用記憶體:0Start @1287562243.58(1009372)|------->End @1287562244.1532(1587544) :|======= 共耗時:0.57321000099182,共用記憶體:578172Start @1287562244.1532(1587544)|------->End @1287562244.6921(1587744) :|======= 共耗時:0.53887605667114,共用記憶體:200


除了兩種方式時間上開始接近外(並且還是正常調用比較利索),記憶體上仍然有天壤之別。失望之餘,查了下網上,發現也有人做了類似的測試。我就直接把結果拷上來吧:
(可能光看結果,會感覺有點難於理解,可以在這裡找到詳細說明:http://vega.rd.no/articles/php-static-method-performance)

測試結果 (ORDER BY time DESC):

PHP code

============Which method========================Time======Inline calculation 0.0805 sNormal function call 0.3438 sNormal method called through object 0.4118 sStatic method called statically 0.4280 sUnspecified method called through object() 0.4294 sUnspecified method called statically() 0.6960 s


如此看來,靜態調用非靜態方法在效能和記憶體上都不佔優勢;另外,此種調用方法容易產生維護混亂。那麼,來個短而有力的總結:靜態調用非靜態方法不可取。[code=PHP][/code][code=PHP][/code]

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.