回答
我喜歡把OOP看作是一個容器內的數據封裝(對象),再加上可以用這些數據完成的一部分操作。還有更多,但是讓我們假設這個簡單的定義是全部的,並且從Lua中構建了一些東西(對其他OO實現的一些熟悉也可以對讀者有很大的幫助)。
由於任何人只要有一點點暴露在Lua中可以知道,表是存儲鍵值對,並用繩子組合整潔的方式,事情開始變得很有趣:
local obj = {} -- a new table
obj["name"] = "John"
obj["age"] = 20
-- but there's a shortcut!
print("A person: " .. obj.name .. " of the age " .. obj.age)
字符串值因爲表中的鍵可以以非常相似的方式訪問C中的結構成員或C++/Java和類似語言中的對象的公共成員。
現在爲了一個很酷的魔術:讓我們結合這個匿名函數。
-- assume the obj from last example
obj.hello = function()
print("Hello!")
end
obj.goodbye = function()
print("I must be going.")
end
obj.hello()
obj.goodbye()
太棒了吧?我們現在有了將函數存儲在表格中的方法,並且您可以再次看到它類似於其他OOP語言中方法的使用方式。但缺少一些東西。我們如何在我們的方法定義中訪問屬於我們對象的數據?這通常是通過改變功能的簽名在表中是這樣解決的:
-- assume the obj from last example
obj.inspect = function (self)
print("A person: " .. self.name .. " of the age " .. self.age)
end
obj.hello = function (self)
print(self.name .. ": Hello! I'm " .. self.name)
end
obj.goodbye = function (self)
print(self.name .. ": I must be going.")
end
-- now it receives the calling object as the first parameter
obj.inspect(obj) -- A person: John of age 20
obj.hello(obj) -- John: Hello! I'm John
obj.goodbye(obj) -- John: I must be going
這解決了它以簡單的方式。也許在Python中工作的方式(方法總是得到一個明確的自己)可以幫助你瞭解Lua如何工作。但是男孩,在我們的方法調用中明確地傳遞所有這些對象不是不方便嗎?是啊,很困擾我太多,所以有另一種快捷方式,以幫助您在使用OOP的:
obj:hello() -- is the same as obj.hello(obj)
最後,我剛剛觸及到如何可以做到這一點的表面。如在Kevin Vermeer's comment中已經注意到的那樣,Lua Users Wiki是關於該主題的極好信息來源,並且您可以瞭解如何實現在此答案中忽略的OOP的另一個重要方面(私有成員,如何構造對象,繼承,...)。請記住,這種做事方式只是Lua哲學的一小部分,爲您提供了構建更高級構造的簡單正交工具。
對於一個快速和骯髒的OO實現我做這樣的事情 -
function newRGB(r,g,b)
return {
red=r;
green=g;
blue=b;
name='';
setName = function(self,name)
self.name=name;
end;
getName = function(self)
return self.name;
end;
tostring = function(self)
return self.name..' = {'..self.red..','..self.green..','..self.blue..'}'
end
}
end
,然後可以使用像 -
blue = newRGB(0,0,255);
blue:setName('blue');
yellow = newRGB(255,255,0);
yellow:setName('yellow');
print(yellow:tostring());
print(blue:tostring());
一個更全功能的方法,我會用一個面向對象的庫作爲被eemrevnivek提及。您還可以找到一個簡單的課程功能here,它位於圖書館的全部和快速和骯髒之間。
我通常使用的方法是這樣的:
class = {} -- Will remain empty as class
mt = {} -- Will contain everything the instances will contain _by default_
mt.new = function(self,foo)
local inst={}
if type(foo) == "table" then
for k,v in pairs(foo) do
inst[k]=v
end
else
inst.foo=foo
end
return setmetatable(inst,getmetatable(class))
end
mt.print = function(self)
print("My foo is ",self.foo)
end
mt.foo= 4 --standard foo
mt.__index=mt -- Look up all inexistent indices in the metatable
setmetatable(class,mt)
i1=class:new() -- use default foo
i1:print()
i2=class:new(42)
i2:print()
i3=class:new{foo=123,print=function(self) print("Fancy printing my foo:",self.foo) end}
那麼,結論是:和元表和一些聰明的想法,關於什麼是可能的:元錶帶班工作時是真正的魔法。
我看到的最佳解決方案並不是在Lua中實現面向對象,它不是自然的和不規則的,因此需要很多行;相反,使用luabridge或luabind在C++中實現它,它是自然而強大的!
它採用LuaBridge簡約的例子:
m.class_<MyClass>("MyClass")
.constructor<void (*) (/* parameter types */)>()
.method("method1", &MyClass::method1)
.property_rw("property2", &MyClass::getter2, &MyClass::setter2)
.property_ro("property3", &MyClass::property3)
這將轉化爲自然LUA語法:
c=MyClass()
c.method1()
c.property2 = c.property3 * 2
do_stuff(c.property3)
同樣一個級別的傳承支持...
這已經是回答,但無論如何,這是我的oop實現:middleclass。
該lib爲創建類,實例,繼承,多態性和(原始)mixins提供了可接受的性能。
樣品:
local class = require 'middleclass'
local Person = class('Person')
function Person:initialize(name)
self.name = name
end
function Person:speak()
print('Hi, I am ' .. self.name ..'.')
end
local AgedPerson = class('AgedPerson', Person) -- or Person:subclass('AgedPerson')
AgedPerson.static.ADULT_AGE = 18 --this is a class variable
function AgedPerson:initialize(name, age)
Person.initialize(self, name) -- this calls the parent's constructor (Person.initialize) on self
self.age = age
end
function AgedPerson:speak()
Person.speak(self) -- prints "Hi, I am xx."
if(self.age < AgedPerson.ADULT_AGE) then --accessing a class variable from an instance method
print('I am underaged.')
else
print('I am an adult.')
end
end
local p1 = AgedPerson:new('Billy the Kid', 13) -- this is equivalent to AgedPerson('Billy the Kid', 13) - the :new part is implicit
local p2 = AgedPerson:new('Luke Skywalker', 21)
p1:speak()
p2:speak()
輸出:
Hi, I am Billy the Kid.
I am underaged.
Hi, I am Luke Skywalker.
I am an adult.
- 1. 如何用Lua Metatables實現OO?
- 2. OO實現RFC 2445
- 3. Lua實現*
- 4. 如何在lua中實現重做
- 5. 如何在lua中實現接口?
- 6. 實現Lua for C#
- 7. 在Haskell中實現這個OO概念
- 8. C++中的最佳OO設計實現?
- 9. 如何用OO實現一組用kdtree的C++密鑰
- 10. 如何使用原型框架在Javascript中實現OO?
- 11. 我的Lua OOP實現
- 12. Lua&OO,如何從另一種方法訪問方法?
- 13. 最佳實踐OO
- 14. 爲動態OO程序實現現有的腳本語言
- 15. 如何OO場景
- 16. 如何在Conky中實現一個基本的Lua函數?
- 17. 如何使用Lua中自己的唯一鍵實現映射?
- 18. 如何在Python中實現Lua邊界模式?
- 19. 如何在Lua中使用Cocos2d-x實現此模式
- 20. Lua oop - 定時器的實現
- 21. 描述Lua 5.2實現的文檔?
- 22. Lua的跨平臺C#實現
- 23. 實現C++ -to-lua觀察者模式?
- 24. 在Lua中實現OOP的意義
- 25. Lua - 實現用戶數據迭代器
- 26. 爲菜單系統實現lua回調
- 27. 在Lua表中實現fallback/default-getter
- 28. OO設計 - 通過接口公開實現細節
- 29. 在c中寫入oo Lua接口的最佳方法?
- 30. 如何實現
我將增加獎勵它,一旦我弄清楚如何,在讓我們說「大約一個星期的」得到這麼頂端回答: ) – 2011-01-25 21:37:21
你的意思是像C++?那麼,最好不要進入這場辯論:( – 2011-01-25 21:37:51
Lua的PIL有詳細的參考資料http://www.lua.org/pil/16.html – 2011-02-05 15:47:23