Lua學習摘記

2021-10-07 23:27:37 字數 3567 閱讀 5398

**lua的物件導向實現很有趣,lua的基本資料型別有8個 nil ,number ,string , boolean , function , table , userdata , thread 。其中的table就是實現物件導向的重中之重 ,lua對table的一些機制設計十分巧妙,只需要熟悉這些機制 ,用簡潔的**就能實現物件導向,不得不讓我佩服lua語言設計者的厲害!

每個table都可以有自己的原表,但table建立新的表時並不會建立原表,即其原表為nil

t=

print

(getmetatable

(t))

--> nil

使用元方法getmetatable,獲取其原表,列印輸出,結果為nil。可以使用setmetatable的方法給表設定原表

t=

metatable=

setmetatable(t,metatable)

print(getmetatable(t))--> table:0x005a11f2

看到輸出的結果為原表的位址。

元方法是個非常牛x的機制,我們知道c++ ,c#裡有個概念叫過載預算符,就是可以自定義加減乘除的運算子方法,lua也提供了這樣的功能,不過lua是靠原表元方法__add(+),__sub(-),__mul(*),__div(/)來實現的,比如我們可以通過這些方法實現兩個table進行相加,即求合集的功能

set=

local metatable=

function set.new(l)

local set=

setmetatable(set,metatable)

for _,v in ipairs(l)

do set[v]

=true

endreturn

setend

function set.union(a,b)

local res=set.new(

)for k in pairs(a)

do res[k]

=true end

for k in pairs(b)

do res[k]

=true end

return res

ends1=set.new

s2=set.new

print(getmetatable(s1))

print(getmetatable(s2))

metatable.__add=set.union

s3=s1+s2

forvin pairs(s3)

do print(v)

endprint(s3)

輸出結果如下:

table: 0x006a19f0

table: 0x006a19f012

3457

89table: 0x006a1ce8

lua也提供了一些關係類的元方法,比如:__eq,__lt,__le,下面來介紹下最重要的乙個元方法,__index

lua模擬物件導向,少不了它。

如何實現類?

首先要建立這樣的概念,就是每個物件要有乙個原型(prototype),當物件的例項遇到乙個未知操作時,原型先會去查詢這個操作,找到了就回去執行它。如果有兩個物件a和b,把b作為a的原型,我們輸入如下語句

```bash

setmetatable(a,)

那麼當a遇到位置操作時就會在b中查詢有沒有這樣的操作。

熟悉物件導向我們知道,乙個類包含建構函式,字段,屬性,方法,那麼我們用下面的**來模擬乙個類

account=

function account:new(o)

o=o or

setmetatable(o,self)

self.__index=self

return o

endfunction account.withdraw(self,v)

self.balance=self.balance-v

enda=account:new

;a.withdraw(a,1)

print(a.balance)

這段**裡我們用到了__index,它的意思就是設定表的原型索引,這裡我們把account這個table的原表設定為自己,原型索引也設定為自己這個table,分析下**的工作流程,當我們建立了account 的例項a,並呼叫withdraw這個未知操作時,a會先查詢自己的原表,發現原表就是account,那麼去執行withdraw方法時,發現自身並沒有withdraw這個方法,就會去查詢原表裡的元方法__index,然後發現account.__index也是account,那麼就會去呼叫account的withdraw方法。這樣是不是就實現了類的繼承,是不是十分巧妙?如果要實現過載也很簡單,那就在a裡再寫個withdraw方法。

那麼如果要實現多重繼承,例如類似c#裡的介面,怎麼做呢?__上例裡__index只是給了父類自身,要實現多重繼承,我們可以將所有繼承的父類存在一張table裡並且給這個物件設定乙個特殊的原表,__index元方法給乙個函式,讓其可以在父類裡搜尋遍歷所搜父類同名方法,那麼不就實現多重繼承了嗎?上**:

local function search(k,plist)

for i=1,#plist do

local v=plist[i]

[k]if

vthen

return

v end

endend

function createclass(

...)

local c=

local parents=

setmetatable(c,

) c.__index=c

function c:new(o)

local o=o or

setmetatable(o,c)

return o

endreturn c

endnamed=

function named: getname(

)return self.name

endfunction named: setname(n)

self.name=n

endaccount=

nameaccount=createclass(named,account)

account=nameaccount:new(

) print(account:getname(

))

分析下這段**,多重繼承的類,它的例項建立是基於多個父類的,那麼就需要乙個特殊的方法createclass,而且是可變長引數,記錄所有父類在parents這個table裡,然後給它的__index方法做乙個特殊處理,就是在parents中遍歷查詢基類方法。當我們建立乙個繼承與named和account的例項後,去呼叫getname方法時自身並沒有getname方法,然後它會去找到它的原表和元方法_index,會在parents裡遍歷找到getname方法,然後去呼叫。

今天的學習筆記就記錄到這~加油!

OSGi學習摘記

最近在學習osgi框架,這篇部落格就當做學習筆記吧。及時更新。osgi是基於不同classloader載入不同的資源模組,而以前的開源框架,例如 hibernate spring sturts等都是基於統一管理和唯一的classloader來設計開發。所以osgi在整合其他框架時需要做特殊處理。im...

lib檔案學習摘記

lib有靜態lib和動態lib之分。在windows上,lib的字尾為lib,在linux上,靜態lib的字尾為a和動態lib字尾為so。1 lib是編譯時需要的,dll是執行時需要的。如果要完成源 的編譯,有lib就夠了。如果也使動態連線的程式執行起來,有dll就夠了。在開發和除錯階段,當然最好都...

perl學習摘記4

模式匹配由反斜線包含 def 即模式def 檢驗匹配是否成功 result var abc 若在該字串中找到了該模式,則返回非零值,即true,不匹配則返回0,即false。則相反 模式中的特殊字元 字元 意味著乙個或多個相同的字元,如 de f 指def deef deeeeef等。它盡量匹配盡可...