Lua面向对象编程
1、__index学习
【前置知识】
setmatatable:设置元表
setmetatable(table1, metatable)
metatable里一般实现__index、__newindex、__add等元方法实现对table的某种操作
当__index为表时
通过键值访问table时,如果没有这个键,那么Lua就会寻找table的metatable中__index表里的key键
性质很像继承关系的父亲
【代码】
t1 = {area = 0}
t2 = setmetatable(t1, {__index = {width = 1}})
-- 此时t1 等价t2 有相同的地址空间
print(t1.area)
print(t1.width)
t1.area = 2
print(t2.area)
print(t2.width)
t2.width = 2
print(t1.area)
print(t1.width)
【运行结果】
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CO1UTO3IGO3EjYlRTNwU2YxYzX2ITNxMDMxMzLcJTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
__index实现继承关系
【代码】
--继承关系
Shape = {area = 0}
function Shape:new(o, side)
o = o or {}
setmetatable(o, self)
self.__index = self --保持继承链,不加此行, t1就没有__index元方法,下面的t2 = it:new({}, 4)会报错
side = side or 0
o.area = side * side
return o
end
t1 = Shape:new({key1 = 1}, 3)
print("t1.area:", t1.area)
print("t1.key1:", t1.key1)
t2 = t1:new({key2 = 2}, 4)
print("t2.key1:", t2.key1)
print("t2.key2:", t2.key2)
t3 = t2:new({key3 = 3}, 5)
print("t3.key1:", t3.key1)
print("t3.key2:", t3.key2)
print("t3.key3:", t3.key3)
【运行结果】
当__index为函数时
通过table.key查找时,会将table和key作为参数传给函数
【代码】
t = setmetatable({key1 = "hsj"}, {__index = function(table, key)
if key == 'key2' then
return 'yes'
else
return 'no'
end
end})
print(t.key2)
【运行结果】
2、__newindex学习
正常的table当对表中一个不存的key进行赋值,会产生一个新的key值保存。当用了__newindex后,则table不会产生新的key值,而对metatable产生新的key保存
【代码】
t = {}
print("t.key:", t.key)
t1 = setmetatable({},{__newindex = t})
t1.key = 1
print("t1.key:", t1.key)
print("t.key:",t.key)
【运行结果】
__index和__newindex混合使用
【代码】
t2 = {}
t = setmetatable({key1 = "hsj"}, {__index = function(table, key)
if key == 'key2' then
return 'yes'
else
return 'no'
end
end,
__newindex = t2
})
t.key2 = 2
print("t2.key2:", t2.key2)
print("t.key2:", t.key2)
【运行结果】
【私密性】
相当于private
__index和__newindex创建一个只读的table
--只读table
function readOnly(t)
local answer = {}
local mt = {
__index = t,
__newindex = function(t, k, v)
error("attempt to update a read-only table", 2)
end
}
setmetatable(answer, mt)
return answer
end
t1 = {1, 2, 3, 4, 5}
t2 = readOnly(t1)
print(t2[1])
t2[1] = 5 --无法修改
__call
__call 元方法在 Lua 调用一个值时调用。
self或表名均可
【代码】
mytable = setmetatable({10}, {
__call = function(self, value)
print("value:", value)
end
})
print(mytable(10))
mytable = setmetatable({10}, {
__call = function(mytable, value)
print("value:", value)
end
})
print(mytable(10))
【运行结果】
重载__add元方法
--只读table
t = setmetatable({1, 2, 3},{
__add = function(self, newtable)
len1 = #self
len2 = #newtable
sum = 0
for i=1, len1 do
sum = sum + self[i]
end
for i=1, len2 do
sum = sum + newtable[i]
end
return sum
end
})
t1 = {2,3,4}
answer = t + t1
print("answer:", answer)
其他类似的元方法
__add(a, b) 对应表达式 a + b
__sub(a, b) 对应表达式 a - b
__mul(a, b) 对应表达式 a * b
__div(a, b) 对应表达式 a / b
__mod(a, b) 对应表达式 a % b
__pow(a, b) 对应表达式 a ^ b
__unm(a) 对应表达式 -a
__concat(a, b) 对应表达式 a .. b
__len(a) 对应表达式 #a
__eq(a, b) 对应表达式 a == b
__lt(a, b) 对应表达式 a < b