2007年03月7日

PHP 實踐 mix-in 概念之可行性

動態語言 php ruby

最近在學習 Ruby 的過程中,接觸到'Mix-in' (混成) 這個新名詞。雖然是個新名詞,但其概念嚴格說來並非 Ruby 所獨有。

Mix-in (混成) 之基本概念在令行為抽象化,使其與特定類別或實例無關。我們再將這些抽象行為組成新的類別或個體。早期的模組化編程概念,其實就已經建立了這種概念, Ruby 則是聰明而有效結合模組與類別,增加許多設計彈性。


Ruby 可以這麼做,那其他語言呢? C/C++ 自然不用說,事實上, C/C++ 可以深入到系統層級實現任何程序員想做的事。說到這就扯遠了,我們當然希望在語言層級上實現混成概念。我想想, JavaScript 可以,那麼 PHP 呢?這篇文章的標題可還寫著 PHP ,當然要談。

說明 PHP 能否實踐混成(mix-in)概念之前,我們先來看 JavaScript 怎麼做?

Invoking variable function without access object context

儘管 PHP 沒有函數指標、函數個體等功能,但藉著以「名」參照的方式,我們可以使用 Variable function 。自 PHP3 以來的長久時間中,我們一直藉 Variable function ,享受動態的函數調用技巧。那麼它能否實踐混成概念呢?首先我們先看一段基本程式。

首先,我定義了一個獨立的函數bar1。接著定義一個類別O,其中以 __set 指派要混成行為的函數名稱,再以 __call 調用混成的行為。結果證實這是可行的,我們心裡可以先竊喜一下。

How about access object context

不要高興太早,函數bar1並沒有嘗試存取任何個體成員,它是一個完全獨立的函數。我們目前只證明它可以混成為類別行為。所以接下來我們要嘗試這樣的函數能否存取個體成員,就像開頭那個 JavaScript 程式所做的事一樣。

一拍兩瞪眼,廢話不多說。從bar2bar4 都發生錯誤。 PHP 的錯誤訊息很明顯地告訴我們,$this 關鍵字不能用在類別以外的函數中,這不像 JavaScript 的 this 會自動依情境指涉關聯個體。

儘管如此,函數bar4的錯誤訊息卻透露出了一絲絲曙光,它的訊息是不允許存取成員。這不難想像,畢竟我們宣告該成員為 private ,所以外部函數無法存取。但有 C/C++ 經驗的程序員這時應該聯想到夥伴函數(friend function) 了,如果我們宣告函數bar4 為類別的夥伴不就能存取了嗎?遺憾的是, PHP 不提供夥伴宣告功能,所以目前暫時做不到。

Access public member of instance

外部函數不能存取受保護的成員,又不能宣告為夥伴,那麼退一步想吧,只要是公開成員就可以做到了吧。

類別O2O類似,差別在其$name為公開成員。這一次終於可行了。

到目前為止,雖然 PHP 已經具有比 Java/C# 更良好的設計彈性,但作為一個動態語言還有許多地方需要改進。暫且先期待 PHP6 的成長吧。


Posted by shirock at 樂多Roodo! │22:56 │回應(0)引用(5)PHP
樂多分類:網路/3C 共同主題:PHP基本語法 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/2817003
引用列表:
之前提過一篇 Prototype-based programming in PHP ,後來在石頭閒語那裡也看到
我也來實作 PHP mix-in 的概念【網站製作學習誌】 at 2007年03月10日 10:23
石頭成老大說他要為他的 mix-in 實作 part 2 ,我也想到了一些好玩的東西。記得很久之前我寫過一篇
我也來實作 PHP mix-in 的概念 - Part 2【網站製作學習誌】 at 2007年03月14日 22:42
隨著混成概念於其他語言之實踐方式逐漸完善,對於「繼承」的想法與實踐途徑必然會更加豐富,設計方式也將更具彈性。
類別繼承、介面宣告與模組混成(mix-in)【石頭閒語】 at 2007年03月16日 11:05
Delegate in C# and Module in Ruby. 與 Ruby 的模組語法相比,不難發現 delegate 的語法冗長多了。
Delegate in C# and Module in Ruby【石頭閒語】 at 2007年03月18日 18:04
為 PHP 實踐一個可以混成的類別 - MixableClass。
PHP 實踐 mix-in 概念 part 2 - MixableClass【石頭閒語】 at 2007年03月20日 14:52