Lua的物件導向

2021-07-25 21:12:05 字數 4091 閱讀 7940

__index元方法用來對錶訪問,__newindex元方法用來對錶更新 。

當通過鍵來訪問table的時候,如果這個鍵沒有值,那麼lua就會尋找該table的metatable(如果有metatable)中的__index鍵。如果__index指向乙個**,lua會在**中查詢相應的鍵,如果__index指向乙個函式,lua會將以table和key作為引數呼叫該函式,並返回該函式的返回值。

第一法則:訪問表元素時的規則:

1.在表中查詢,如果找到,返回該元素,找不到則繼續

2.判斷該錶是否有元表,如果沒有元表,返回nil,有元表則繼續

3.判斷元表有沒有__index鍵,如果__index為nil,則返回nil;如果__index指向乙個表,則重複1、2、3;如果__index指向乙個函式,呼叫該函式並返回該函式的返回值

第二法則:更新表元素的規則:

1.如果table有該元素,直接為該元素更新值;

2.如果table無該元素,且table的元表為nil或元表不為nil但元表的__newindex為nil,則直接為table新增元素;

3.如果table無該元素,且存在元表,元表的__newindex不為nil,則通過__newindex來操作,具體是:如果__newindex指向乙個表,重複上述步驟;如果__newindex指向乙個函式,以table,key,value作為引數呼叫該函式。

第三法則:語法糖「:」

-- 定義函式時,相當於把:換成.並將self作為第乙個形參;

-- 呼叫函式時,相當於把:換成.並將呼叫函式的table作為第乙個實參。

t={}

functiont:f

()print

(self)

endt

:f()

乙個簡單例項:

rectangle = 

function rectangle

:new (o,length,breadth)

local o = o or {}

setmetatable(o, self)

self.__index = self

self.length = length or

0self.breadth = breadth or

0self.area = self.length*self.breadth

return o

endfunction rectangle

:printarea ()

print("矩形面積為", self.area)

endmyshape = rectangle

:new(nil,2,10)

myshape:printarea()

在myshape.printarea(myshape)中:

因為myshape裡邊沒有printarea,去找元表rectangle的__index,__index指向rectangle,rectangle裡有printarea,所以就去呼叫rectangle的printarea。在rectangle的printarea裡列印myshape.area,myshape裡沒有area,又去rectangle的__index裡找,找到並列印了出來。

但是在這裡,資料不是儲存在「new」出來的例項中的,而是儲存在rectangle中,這就像c++裡類的靜態成員變數和靜態成員函式。比如這樣用:

myshape1 = rectangle:new(nil,2,5)

myshape2 = rectangle:new(nil,4,10)

myshape1:printarea()

myshape2:printarea()

列印出來的都是40。

我們換一種更好的方式

rectangle = {}

rectangle.__index = rectangle

function

rectangle.new (length,breadth)

local o = {}

setmetatable(o, rectangle)

o.length = lengthor0

o.breadth = breadth or

0 o.area = o.length*o.breadth

return o

endfunction

rectangle:printarea ()

print("矩形面積為", self.area)

endmyshape1 = rectangle.new(2,10)

myshape2 = rectangle.new(4,10)

myshape1:printarea()

myshape2:printarea()

通過__index實現繼承的例子如下:

rectangle = {}

rectangle.__index = rectangle

function

rectangle.new

(length, breadth)

local o = {}

o.length = length or

0 o.breadth = breadth or

0setmetatable(o, rectangle)

return o

endfunction

rectangle:getarea

() return self.length * self.breadth

endcube = {}

setmetatable(cube, rectangle)

cube.__index = cube

function

cube.new

(length, breadth, height)

local o = rectangle.new(length, breadth)

o.height = height or

0setmetatable(o, cube)

return o

endfunction

cube:getvolume

() return self.height * self:getarea()

endr1 = rectangle.new(2,3)

r2 = rectangle.new(3,4)

print("r1的長是", r1.length, "寬是", r1.breadth)

print("r1的面積是", r1:getarea())

print("r2的面積是", r2:getarea())

c1 = cube.new(4,5,6)

c2 = cube.new(3,4,5)

print("c1的面積是", c1:getarea())

print("c1的體積是", c1:getvolume())

print("c2的面積是", c2:getarea())

print("c2的體積是", c2:getvolume())

--[[輸出是:

r1的長是 2 寬是 3

r1的面積是 6

r2的面積是 12

c1的面積是 20

c1的體積是 120

c2的面積是 12

c2的體積是 60

]]--

關鍵在於setmetatable(cube, rectangle)和setmetatable(o, cube),在c1中查詢getvolume時,會在c1的元表cube的__index指向的cube中查詢,正好找得到;在c1中查詢getarea時,卻找不到,於是去cube的元表rectangle的__index指向的rectangle中查詢,就找到了。

雖然lua也可以模擬實現封裝、抽象、派生,但也有點太麻煩了,特意的oo可能反而得不償失,要充分利用lua本身的機制,靈活應用,再說oo應該交給宿主語言c++去做。

lua物件導向

直接貼 參考的也是別人的,只不過其中幾點,增加一點自己的理解 local baseclass print baseclass是 tostring baseclass 定義index屬性,指向本身 baseclass.index baseclass 定義建構函式 function baseclass ...

Lua 物件導向

記錄學習過程 建立日期 2019 04 14 物件由屬性和方法組成。lua中最基本的結構是table,所以需要用table來描述物件的屬性。lua 中的 function 可以用來表示方法。那麼lua中的類可以通過 table function 模擬出來。乙個簡單的物件導向例子 屬性 person ...

Lua 物件導向

我們知道,物件由屬性和方法組成。lua中最基本的結構是table,所以需要用table來描述物件的屬性。lua中的function可以用來表示方法。那麼lua中的類可以通過table function模擬出來。至於繼承,可以通過metetable模擬出來 不推薦用,只模擬最基本的物件大部分夠用了 l...