關于luac文件:
預編譯并非意味著執(zhí)行更快速呵恢,因為Lua中的單元總會在執(zhí)行前被編譯為字節(jié)碼峡懈。luac只不過允許這些字節(jié)碼被存為文件用于以后的運行鸡典。
預編譯單元(的尺寸)并不比對應的源代碼小挣菲。它的主要目標是加快裝載贮喧。
lua里面實現class機制,比較關鍵的地方就是class的繼承機制舔庶,以及class實例化的過程。
class繼承機制的關鍵是怎么讓子類擁有父類的方法集:
1.完全使用setmetatable()的方式實現惕橙,每繼承一次肚逸,都把父類的方法集設置為子類方法集的metatable犬钢。這樣做應該最符合class的繼承的思想混滔,盡可能的復用邏輯坯屿,而且可以做到動態(tài)更新父類的方法集后乏德,所有子類都會焙螄磧姓庀罡碌奶匭?比如滿足某些特殊的動態(tài)更新需求)喊括。但隨著class繼承的層次加深,會生成一個復雜的class方法集table(n層的metatable)蘑拯,畢竟metatable是有額外開銷的,所以這個方法不一定是最完美的方案。
2.將父類方法集copy到子類方法集來實現繼承玄窝,即每當定義一個新的子類時趣斤,都將父類中方法集完整copy到子類方法集中玉凯。這種方法避免了使用metatable()帶來的額外開銷漫仆,但卻造成了一些數據冗余(其實并不多)署照,并喪失了父類更新子類也會自動更新的特性建芙。
3.方案2的改進版本(也就是云風這里使用的比較強悍的方式:P pf),即同樣是采用copy父類方法集的方案禁荸,但卻改進了copy的機制炕倘。將原本在class定義期執(zhí)行的方法集copy工作轉移到實例的運行期間啊央,采用copy-on-use(等同于copy-on-write的設計思路)的方式涨醋,在子類實例用到父類的某個方法時瓜饥,才將其copy到子類的方法集中。由于這種copy只發(fā)生一次浴骂,而且不見得子類會用到父類方法集中的所有內容(事實如此)乓土,所以這個方案相對于方案2來說減少了冗余數據,但卻幾乎沒有增加任何額外開銷溯警。
class實例化關鍵是實例如何享有class的方法集:
1.最爛的方式趣苏,方法集copy,即class實例化時梯轻,將class的方法集直接copy給實例的數據table食磕。這樣的好處就是每個實例創(chuàng)建后,外界除非直接操作實例的數據table喳挑,否則其它行為都不會影響到這個實例的所有屬性和特征(也許可以滿足某些特殊的需求吧),同時也省掉了一次metatable的查找開銷彬伦。缺點很明顯滔悉,實例化過程低效,而且產生大量的冗余信息(或者這里也采用copy-on-use的思想? :p)单绑。
2.采用將class方法集設置為實例的metatable的方式回官,使實例享有class的方法集(這要求實例的數據類型必須可以擁有自己的metatable,即只能是table或userdata)搂橙。這個方案更優(yōu)雅一些歉提,而且符合class的共享思想并且實例化開銷很小,應該是實現實例化的最佳方案了区转。在實現子類的初始化函數時唯袄,一般的思路都是先生成一個父類的實例,再強制將當前子類的方法集設置為這個實例的metatable蜗帜。
目前我們采用的class機制就是上述的兩個2號方案(考慮更新到云風的3號方案),自己實現了兩個接口class_define()、class_inherit()资厉,其實完成的功能等同于以上代碼中的class()厅缺。還是很pf lua的作者,估計在設計lua時就考慮到了面向對象的實現問題宴偿,很class的多關鍵機制(如隱式self參數湘捎、metatable機制)都已實現,這為自己實現class機制提供了強有力的支持窄刘。加上腳本的弱數據類型特性窥妇,只要思路清晰,在C++中可以實現的class機制lua中基本都能實現一個翻版娩践,也許下個版本的lua可能會顯示支持class:)