表
表应该是lua语言中的精髓
1. 表的内容赋值
- 通过tableName.key = value 赋值
- 通过tableName[“key”]=value 赋值
- 无键赋值,tableName[index]=value 赋值
2. 表的基础操作
2.1 表长:#tableName
只能对数组进行求长度,不能对表求长度
2.2 元素插入:table.insert(tableName,var)
2.3 元素删除: table.remove(tableName,var)
让表成为模板,自定义表的参数
code<1-1>
-- 定义创建学生对象的函数
function createStudent(name, age, grade, height)
local student = {
name = name,
age = age,
grade = grade,
height = height
}
return student
end
-- 创建两个学生对象
local jack = createStudent("Jack", 20, "A", 180)
local mike = createStudent("Mike", 22, "B", 175)
3. 元表
我们知道通过面向对象设计可以对类进行功能补充,而元表就是对表进行功能补充,例如表与表之间是无法相加的,但是通过__add可以实现表与表相加。
3.1 元表也是对象,方法可以被继承
设置b的元表为mt,让a[2]=b,则a[2]就继承了b的方法
code<3-1>
a= {{1,2},{3,2}}
b={1,2}
mt = {}
mt.__eq= function (tb_a,tb_b)
for i =1 ,#tb_a,1 do
local var1 = tb_a[i]
local var2 = tb_b[i]
if var1 ~= var2 then
return false
end
end
return true
end
setmetatable(b,mt)
a[2]=b
print(a[1]==a[2])
------------------------
true
先看这个函数
code<3-2>
function judge()
return false
end
if not judge() then
print("peace")
end
-----------
peace
此处证明 布尔函数的返回值可以正确的被if函数使用,我们在**code<1-2>**中添加以下代码
code<3-3>
for i =1 ,#a,1 do
print(a[i]==b)
if not a[i]==b then print("love") end
end
----------------
true
false
无输出
Initial cognition:这里证明元表的方法如果是布尔函数,不能正确被if函数使用
Further research : 因为运算符优先级不同,not 优先级大于 ==,导致错误翻译成(not a[i])==b
应该改写为not(a[i]==b)
3.2 应用
code<3-4> 让表+表的表达式成立
local tb_a={2,3,4,5}
local tb_b = {1,2,3,4}
local mt ={}
mt.__add = function (tb_a,tb_b)
local result = {}
for k=1,#tb_a,1 do
-- result[k]=tb_a[k]+tb_b[k] (此行代码只能让同长度的表相加)
local var1 = tb_a[k] or 0 -- 采取这样的方法需要在for循环的条件那里比较tb_a与tb_b中长度最大的
local var1 = tb_a[k] or 0
result[k]=var1+var2
end
return result
end
setmetatable(tb_a,mt)
local tb_c = tb_a+tb_b
for k,v in ipairs(tb_c) do
print(v)
end
-------------------------------------
3
5
7
9
code<3-5>打印表里的所有元素
metatable = {}
--设置元表
metatable.__tostring=function (tb) --此处的tb是整个表students
local result="{"
for _,k in pairs(tb)do
result = result..tostring(_).." = "..tostring(k)..","
end
if #result > 1 then
result = result:sub(1, -2)
end
result = result .. "}"
return result
end
local students ={}
students.name = "jack"
students[2]="male"
students["age"]=3
--布置元表
setmetatable(students,metatable)
print(students)
------------------------------------------
{2 = male,name = jack,age = 3}
3.3 面向对象的继承与方法查找
3.4 什么叫继承?
顾名思义是子类继承父类的某些属性和方法
此处贴一段常见基类的代码
code<3-5>
-- classic.lua: A simple class module for Lua
local Object = {}
Object.__index = Object
-- 通过Object:extend()构建的子类,都具有Object以__开头的方法,同时有让Objecti成为了子类的元表,则相当于子类继承了父类所有的方法
function Object:extend()
local cls = {}
for k, v in pairs(self) do
if k:find("__") == 1 then
cls[k] = v
end
end
cls.__index = cls
cls.super = self
setmetatable(cls, self)
return cls
end
function Object:new()
end
function Object:__call(...)
local instance = setmetatable({}, self)
instance:new(...)
return instance
end
return Object
3.5 什么叫方法查找
首先一个类具有其定义的方法,如果该类调用自己没有的方法,lua机会查找该表是否具有元表,如果没有元表则报错。如果有元表则看元表的__index字段,如果该字段是一个函数则调用该函数,如果字段指向元表自身,则在元表内查找方法。
local tb = {}
function tb:a()
print("我是tb里的函数")
end
local metatb={}
-- 令元表的__index指向元表本身,则表中没有的方法就会在元表内查找
metatb.__index = metatb
metatb.name = function ()
print("name is metatb")
end
--设置元表
setmetatable(tb,metatb)
tb:a() -- 表自身有的方法
tb:name() ---表没有的方法,调用元表,表在元表中找到方法
-----------------------------
我是tb里的函数
name is metatb