t = {}
table.insert(t,100)
table.insert(t,1000)
table.insert(t,10000)
table.insert(t,1,10)
table.insert(t,2,50)
print(table.remove(t)) --10000
print(table.remove(t,4)) --1000
for k,v in pairs(t) do
print(v) --10 50 100
endtable.insert(操作的table [,位置=#t+1] ,值)
table.remove(操作的table[,位置=#t])
key1 = {"one"}
key2 = {"two"}
t = {}
setmetatable(t,{__mode="kv"})
t[key1] = 10
key1 = nil
t[key2] = 100
key2 = nil
collectgarbage() --主动调用gc回收垃圾
for k,v in pairs(t) do
print(k,v)
endt的key值是一些table,后面被赋值为nil了,表明其实这条数据是不需要的了,但是gc是不知道的,这些table的key被存在的table引用着。
所以使用弱引用,设置table的元表的元方法__mode(一个字符串),带有k表示key值为弱引用,带有v表示value是弱引用,反正出现弱引用的值被nil了,整个条目都会被移除。
function newObject(value)
return function(action,v)
if action == "get" then return value
elseif action == "set" then value = v
else error("invalid action")
end
end
end
d = newObject(0)
print(d("get")) --0
d("set",100)
print(d("get")) --100value值应该就是那个非局部变量了,每个对象用到一个closure,比用一个table高效。
local function search(k,plist)
for i=1,#plist do
local v = plist[i][k]
if v then return v end
end
end
function createClass(...)
local o = {}
local parents = {...}
setmetatable(o,{__index=function(t,k)
local v = search(k,parents)
t[k] = v
return v
end
})
o.__index = o
function o:new(p)
p = p or {}
setmetatable(p,o)
return p
end
return o
end
Named = {}
Named.a = 10
Tell = {}
Tell.b = 50
Acc = createClass(Named,Tell)
acc = Acc:new()
print(acc.b)多重继承的话就不能通过某一个类来创建新的类型了,需要通过第三方的方法来创建类,参数传入基类们,创建一个新的table,它的元方法为可以在基类们中搜索对应值的search方法,缓存基类方法到具体的table(缺点是运行时修改基类的方法不会向下传递了,优点是访问加快了),为新table(类)提供一个new方法来创建对象,就是设置新table类为新新table的元表的__index。
People = {name='Chicai'}
function People:New(o,name)
o = o or {}
setmetatable(o,self)
self.__index = self
name = name or 'Chicai'
self.name = name
return o
end
function People:printName()
print(self.name)
end
Boy = People:New({sex='boy'})
function Boy:printSex()
print(self.sex)
end
me = Boy:New()
me:printName()
me:printSex()Boy是People的一个对象(Boy的元表的__index方法是People),Boy有自己的属性sex和方法printSex
me是Boy的一个对象,Boy调用继承过来的New方法,但是self参数改为了Boy,也就是说me的元表的__index是Boy
当me调用方法,在me中找不到时,就会去Boy的__index(还是Boy)中找,Boy也找不到,就去People找,调用时,self为me了
People = {name='Chicai'}
function People:New(o,name)
o = o or {}
setmetatable(o,self)
self.__index = self
name = name or 'Chicai'
self.name = name
return o
end
function People:printName()
print(self.name)
end
me = People:New()
me:printName()声明类People,其实是个Table,New方法用来创建实例,创建一个新的table-o代表实例,设置新table的元表为self就是People类,设置元表的__index元方法为self也还是People类,这样很绕,但是想想o就可以访问People定义好的属性和方法了。
me是一个元表为People的table(对象),me访问方法printName时,发现me没有这个方法,就会去元表的__index里面找,找到People:printName并调用,但是self参数传入的是me,调用me.name,同样找不到,到元表中的_index中找。
Account = {b = 0}
function Account.withdraw(self,v)
self.b = self.b - v
return self.b
end
function Account:Haha(v)
self.b = self.b + v
return self.b
end
a = Account;
Account = nil;
print(a.withdraw(a,1)) -- -1
print(a:withdraw(1)) -- -2
print(a.Haha(a,10)) --8
print(a:Haha(10)) --18:只是一种语法,就是一个可以自动添加self参数的语法,声明方法使用:,默认参数带有self,调用使用:时,将把调用方传进来。
例子中可以看.操作的模式,其实就是:实际的真正意思,:只是可以省略不写仅此而已。
array = {}
array.mt = {}
function array.new(t)
local data = {}
for k,v in ipairs(t) do
data[v] = true
end
setmetatable(data,array.mt)
return data
end
array.mt.__le = function(a,b) --<=
for k in pairs(a) do --a是b的子集
if not b[k] then return false end
end
return true
end
array.mt.__lt = function(a,b) --<
return a<=b and not (b<=a)
end
array.mt.__eq = function(a,b) --==
return a<=b and b<=a
end
a1 = array.new{"hello","world"}
a2 = array.new{"love","hello","tttt"}
a3 = array.new{"tttt","love","hello"}
print(a1 >= a2) --false
print(a2 <= a3) --true
print(a2 == a3) --true
print(a2 < a3) --false
print(a1 < a2) --false关系类的元方法的两个操作元素table需要有一致的元表
array = {}
array.mt = {}
function array.new(t)
local data = {}
for k,v in ipairs(t) do
data[v] = true
end
setmetatable(data,array.mt)
return data
end
array.mt.__add = function(a,b)
local data = array.new{}
for k in pairs(a) do data[k] = true end
for k in pairs(b) do data[k] = true end
return data
end
array.mt.__tostring = function(t)
local l = {}
for k in pairs(t) do
l[#l+1] = k
end
return table.concat(l,", ")
end
a = array.new{"one","three","love"}
b = array.new{"you","two","one"}
c = {"hello","world"}
print(a) --three,love,one
print(a+b) --two,one,love,three,you
print(a+c) --1,2,one,love,three
print(c+a) --1,2,three,love,one这些二元的操作符,会先从左操作数找table对应的元方法,如果找到就用它,如果没找到,就找右操作数table的元方法,找到了就用,如果都没有,那就报错了。
Window = {}
Window.prototype = {x=0,y=0,width=100,height=100}
Window.mt = {}
function Window.New(x)
setmetatable(x,Window.mt)
return x
end
Window.mt.__index = function(t,k)
return Window.prototype[k]
end
t = Window.New({})
print(t.width)
Window.mt.__newindex = function(t,n,v)
error("not exists "..n,2)
end
--t.ll = 2 会报错
Window.mt.__index = {width=888}
print(t.width) --888
Window.mt.__newindex = {}
t.ll = 2;
print(t.ll) --nil
print(Window.mt.__newindex.ll) --2__index元方法,主要table访问不存在的元素的时候,就会调用该方法,可以用来做继承,返回一些默认的值,如果__index是一个table,会自动去这个table查找那个值并返回。
__newindex元方法,主要在table对一个不存在属性进行赋值时调用的方法,如果__newindex引用的是一个table,那么会将值添加到这个table中了。