lua学习笔记---7.面向对象

387 阅读2分钟

元表:

  • 改变表的行为(运算符重载/访问不存在的键值),
  • 一类具有相同行为的表具有相同的元表
  • 设置元表:setmetatable(表,元表)
  • 获得元表:getmetatable(表),返回该表的元表

元方法(两个下划线开头):

  • 可以是函数也可以是表
  • 对应不同的行为有不同的元方法

算数运算符的元方法:

     相加:__add  相减:__sub  相乘:__mul
     相除:__div  求余:__mod  指数:__pow
     复数:__unm

关系运算符:

     等于:       __eq    ~= 变为 not ==
     小于:       __lt
     小于等于:   __le

tostring转换为字符串:__tostring

..字符串连接符:__concat

特殊的元方法:

__index:访问不存在的键值(访问)
  • 函数:按照函数逻辑执行
  • 表:
    • 查找元素的__index对应的表t是否有该方法
    • 如果t没有这个方法,继续查找t是否有__index元方法,继续1
-- __index是函数
function Vec2:__index(key) -- 表,键
    -- print("调用了vec2:__index元方法")
    return Vec2[key]
end

-- __index是表
local tb = {}
function tb:getLength()
    print("test")
end
Vec2.__index = tb
__newindex:给不存在的键值赋值时(更新)
  • 函数:按照函数逻辑执行
  • 表t:给表t添加新键值
-- 作用:添加不存在的键值 
-- __newindex是函数
function Vec2:__newindex(key,value)
    -- print("调用了vec2:__newindex元方法")
    error("不允许添加新键值")
end

-- __newindex是表
Vec2.__newindex = Vec2

例子

v1+v2:
  • 先检查v1是否有元表,检查元表中是否有对应的元方法(__add)
  • 如果有,按照元方法逻辑执行
  • 如果v1没有,同理查找v2
  • 如果都没有,就报错

代码

local Vec2 = {x = 1, y = 2} -- 二维向量的类

-- 构造函数
function Vec2:new(x,y)
    -- 构建一个新表并且返回
    local obj = {}
    obj.x = x or 0
    obj.y = y or 0
    -- 设置obj的元表为Vec2
    setmetatable(obj,self)
    -- __index的元方法固定写法
    self.__index = self
    return obj
end

-- 添加__tostring元方法
function Vec2:__tostring()
    return "x = " .. self.x .. ",y = " .. self.y
end

-- 转换为.的形式
-- function Vec2.__tostring(self)
--     return "x = " .. self.x .. ",y = " .. self.y
-- end

-- 添加相加行为的元方法(重载加号运算符):
function Vec2:__add(other)
    -- 逻辑
    local obj = Vec2:new()      --重新创建一个Vec2的对象
    obj.x = self.x + other.x
    obj.y = self.y + other.y
    return obj
end

-- 添加成员函数:求长度
function Vec2:getLength()
    return math.sqrt(self.x ^ 2 + self.y ^ 2)
end

-- 创建对象
local v1 = Vec2:new(3, 4)
print(v1:getLength())       --先查找v1有没有元表,再查找元表有没有getLength()方法
v1.z = 20
print(v1.z)
local v2 = Vec2:new(3, 4)
local v3 = v1 + v2
print(v3)
local v4 = v3 + v2
print(v4)