Lua下通過元表模擬OOP程式設計,繼承多型
Lua本身是沒有以明確的定義來支援OOP程式設計的,但是我們卻可以通過Lua核心提供的一些特性來間接實現簡單的面向物件的程式設計。
通過Lua中的 table結構 metatable 以及函式可以配合實現OOP,以及繼承。這些說白了都是一種偽實現,不建議在Lua下使用多重繼承 。
在LUA中你想要 強制實現OOP 你必須需要懂一下幾個關鍵詞!!
什麼是語法糖?
語法糖即糖衣語法,C/C++升級過程中的面向物件 整體就是一種語法糖 ,是由英國電腦科學家彼得·約翰·蘭達(Peter J. Landin)發明的一個術語,指計算機語言中新增的某種語法,這種語法對語言的功能並沒有影響,但是更方便程式設計師
比如char str[100] ;我訪問第一個 字元 我是不是可以這樣 str[1] *(str+1) 簡化了 程式碼編寫 使粘合度 更高 就是一種語法糖。用過c#的人可以發現,C#的語法糖做到了極致。
什麼是table?
Lua中的結構只有table,他是基於 HashMap 與索引陣列與 一身,能存放任意型別資料,包括函式 何以其他表 這也就是 我們模擬整合的奠定了基礎。
什麼是metable?
local tb={["a"=1]} 這麼一段程式碼 ,假如 我print(tb.b) 那麼會提示找不到b,
這個時候叫做元表的metable 就起作用了,這會觸發lua的 搜尋機制,就去從metatable 中 搜尋 b 這一點是不是和 javascript 的 prototype 型別呢?
這也就是我們實現繼承的基礎
table中的__index是做什麼用的?
他是一個函式,這個函式告訴Lua直譯器 當在一個table中找不到 相對應元素的時候 如何從 metable 中搜索元素。
--語法糖 兩種等價操作 --Class.__index=function(key)return Class[key] end --設定外部搜尋物件 Class.__index=Class --函式呼叫的語法糖等價操作 local a={} --lua中的函式預設都是有self傳遞進去的 語法糖會自動給我們傳遞 self --也就是說通過.呼叫table的函式如果函式內部引用self 需要我們在呼叫的時候手動傳遞物件a進去 --但是通過:呼叫的話 Lua直譯器 預設在每個函式呼叫給我們 吧 a給傳遞進去了 在函式內部引用 就叫做self a:b()== a.b(a) function SubClass:test() print("test is child ") end 我們可以直接 SubClass.test(SubClass) 也可以 直接呼叫 SubClass:test()
實現OOP
--模擬實現OOP
--通過table定義類模型
Class={}
--語法糖 實際上被轉換為
--Class.__index=function(key)return Class[key] end
--設定外部搜尋物件
Class.__index=Class
function Class:new(x) --語法糖而已
print('模擬建構函式!')
local temObj={}
temObj.x=x
--設定meta object
setmetatable(temObj,self)
return temObj
end
function Class:ShowData()
print("self.x:",self.x)
end
function Class:delete()
self.x=nil
print('模擬解構函式!')
end
local clsObj=Class:new(1)
--隱式傳遞clsObj作為 self 引數
clsObj:ShowData()
--顯示傳參作為self引數
clsObj.ShowData(clsObj)
clsObj:delete()
結果如下LUA模擬實現繼承
--模擬實現OOP
--通過table定義類模型
Class={}
--語法糖 實際上被轉換為
--Class.__index=function(key)return Class[key] end
--設定外部搜尋物件
Class.__index=Class
function Class:new()
print('模擬建構函式!')
local temObj={}
--設定meta object
setmetatable(temObj,self)
return temObj
end
function Class:parent()
print("parent is ",type(self))
end
function Class:delete()
print('模擬解構函式!')
end
--從基類建立物件
SubClass=Class:new()
--設定__index搜尋 範圍
SubClass.__index=SubClass
--派生建構函式
function SubClass:new()
local obj={}
--設定派生metable為self 就是 SubClass
setmetatable(obj,self)
--返回物件
return obj
end
---派生物件方法
function SubClass:child()
print("child is ",type(self))
end
--建立一個派生物件
local obj=SubClass:new()
--通過語法糖呼叫不同方法
obj:child()
obj:parent()
--語法糖等價於
obj.child(obj)
obj.parent(obj)
模擬實現多型
既然繼承我們都實現了 多型我們只需要在不同的型別中新增不同的定語法糖函式義即可
--模擬實現多型
Class={}
--語法糖 實際上被轉換為
--Class.__index=function(key)return Class[key] end
--設定外部搜尋物件
Class.__index=Class
function Class:new()
print('基類模擬建構函式!')
local temObj={}
--設定meta object
setmetatable(temObj,self)
return temObj
end
--
function Class:test()
print("test is parent")
end
--從基類建立物件
SubClass=Class:new()
--設定__index搜尋 範圍
SubClass.__index=SubClass
--派生建構函式
function SubClass:new()
local obj={}
--設定派生metable為self 就是 SubClass
setmetatable(obj,self)
--返回物件
return obj
end
--override方法
function SubClass:test()
print("test is child ")
end
--建立一個派生物件
local objChild=SubClass:new()
--建立一個基類物件
local parentObj=Class:new()
parentObj:test();
objChild:test();
參考資料
http://blog.csdn.net/ym012/article/details/7206968
http://www.xuebuyuan.com/1613223.html
http://blog.csdn.net/xocoder/article/details/9028347
http://www.cnblogs.com/zhiranok/archive/2012/02/07/lua_object_skill.html