lua實現面向對象的特性
lua本身不支持面向對象的特性,但是由于lua是基于原型(prototype)的語言,要實現面向對象的特性也是有一定的方法的,實現方式有很多種, 總結了一下我最近對使用lua實現面向對象的特性,主要可以分為以下兩種不同的方式來實現:
1、使用metatable的__index域實現,實現的時候需要利用的lua語言的一些特性才可以實現,主要有:
a、將table b作為table a的一個prototype的方法:setmetatable(a, {__index = b});
b、lua5.1中實現的module機制;
通過這兩個技術你可以實現一個基礎類,實現類的inherit和new方法:
- --filename:"obj.lua"
- local setmetatablesetmetatable = setmetatable
- module"obj" function inherit (self)
- return function (newclass)
- setmetatable (newclass, self)
- selfself.__index = self
- return newclass end
- end
- function new (self, o)
- oo = o or {}
- setmetatable (o, self)
- selfself.__index = self
- return o end
- ----------------------------------------------------------------------
- --Now you can define a new class which extends the previous `obj':
- --filename:"myobj.lua"
- local obj = require"obj"
- module ("myobj", obj:inherit())
- --Class `myobj' will "inherit" the methods `new' and `inherit' from class `obj'.
優點:
1、由于子類的很多數據和方法都是共用了父類的,用到父類的數據和方法的時候,只是在使用的時候才直接調用父類的方法和數據,這樣可以減少程序內存的消耗,更主要的是,父類在運行期的修改是會影響到子類的;
2、充分利用了lua語言的特性,父類的方法和數據的訪問是解析器來做的,所以效率上的開銷還是比較小的;
缺點:
1、如果父類中有一個數據是一個引用的時候(如table)的時候,就會出現在一個子類中操作這個table會改變其他子類的情況,造數據的不 一致,所以應該盡量避免這種類的創建,如果有這樣的需求的話,就需要對inherit和new函數進行一些特殊的操作,簡單來說就是加一個init函數, 將所有這類的數據都顯示的創建一下。
2、由于每次取操作都需要在metatable中取,所以,每次就會增加一層繼承,就增加一個函數調用的開銷,雖然是由解析器來做的,但是如果層次多了的話,還是有開銷的;
3、使用table拷貝的方式實現,實現的時候利用的lua的技術為:
a、使用lua實現一個table拷貝的函數;
b、lua5.1中實現的module機制;
通過這兩個技術你可以實現一個基礎類,實現類的inherit和new方法:
- -----------------------------------------------------------------------
- --filename:"obj.lua"
- local setmetatablesetmetatable = setmetatable
- module"obj"
- function inherit (self)
- return function (newclass)
- newclass = table.clone(self)
- return newclass
- end
- end
- function new (self, o)
- oo = o or {}
- o = table.clone(self)
- return o
- end
- ----------------------------------------------------------------------
- --Now you can define a new class which extends the previous `obj':
- --filename:"myobj.lua"
- local obj = require"obj"
- module ("myobj", obj:inherit())
- --Class `myobj' will "inherit" the methods `new' and `inherit' from class `obj'.
優點:
1、父類中的數據是全部拷貝到子類中的,所以,不存在數據不一致的情況;
2、所有的函數調用和數據調用都是直接調用每個實例的,不需要到父類中查找;
缺點:
1、全部數據的copy,在創建的時候就會增加一個table copy的過程,影響效率;
2、全部數據和方法都是在創建的時候拷貝一份的,會增加很多的內存消耗,而且如果在運行期改變了父類,并不能改變子類;
總結:
結合這兩種方式的有缺點,從一個面向對象的角度來說,第一種方式更加適合實現面向對象的特性,第二種方式對面向對象的模擬就牽強一些(缺點 2),但是從使用的角度來說,因為在訪問數據和方法速度上,第二種方式還是有優勢的,所以,在具體的使用的時候,可以靈活一下使用,將兩者結合一下。
比如說,對于客戶端這邊來說,類在開始創建好了以后就一般不需要修改了,而且子類一般都是需要父類的所有的方法和數據的,所有我們就可以使用第 二種方式,而生成對象實例的時候,對象的實例一般都不會調用類的所有的方法,而且用完了這個實例,就會銷毀的,所以,我們這里就可以采用第一種方式,結合 一下設計可以是:
- -----------------------------------------------------------------------
- --filename:"obj.lua"
- local setmetatablesetmetatable = setmetatable
- module"obj"
- function inherit (self)
- return function (newclass)
- newclass = table.clone(self)
- return newclass
- end
- end
- function new (self, o)
- oo = o or {}
- setmetatable (o, self)
- selfself.__index = self
- return o
- end
- ----------------------------------------------------------------------
- --Now you can define a new class which extends the previous `obj':
- --filename:"myobj.lua"
- local obj = require"obj"
- module ("myobj", obj:inherit())
- --Class `myobj' will "inherit" the methods `new' and `inherit' from class `obj'.
這里的關鍵是繼承是copy出來的,而實例是采用metatable的方式實現的。
原文鏈接:http://tech.it168.com/j/2008-02-17/200802171004466.shtml

























