lua面向对象

建议提前学习https://www.runoob.com/lua/lua-metatables.html

面向对象特征

  • 1) 封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性。
  • 2) 继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。这有利于减少重复编码,提高软件的开发效率。
  • 3) 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
  • 4)抽象:抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题。

lua并没有严格的面向对象的语法,我们只是使用表的特性来模拟类。

lua是duck风格,不存在访问性的问题。所以我们这里考虑如下四种概念:

  • 静态变量:属于该类的变量
  • 静态函数:属于该类的函数
  • 成员变量:属于该类对象的变量
  • 成员函数:属于该类对象的函数

一个类是一个元表,表中存储静态变量、静态函数、以及对象的成员函数。

一个对象是一张表,表中存储了成员变量。

如下表:

属于 代码位置 写法
静态变量 元表 .
静态函数 元表 .
成员变量 对象 .
成员函数 对象 元表 :

示例如下:

Lua 复制代码
A = {             -- 类名为 A
    staticVar = 0 -- 静态变量
}
A.__index = A     -- 当做格式即可


function A.StaticFunc()                   -- 静态函数
    print("staticVar is " .. A.staticVar) -- 可以访问静态变量
end

function A:New(number) -- 定义构造函数,使用其它名称也是可以的
    -- self 类似 this 指针
    local obj = {}
    setmetatable(obj, self)     -- 将对象 obj 的元表设置为类 A
    obj.normalVar = number or 0 -- 使用 or 来制定默认值
    return obj
end

function A:NormalMethod()                    -- 成员函数
    print("normalVar is " .. self.normalVar) -- 可以访问成员变量
end

local a1 = A:New(1) -- 调用构造函数来创建对象
local a2 = A:New(2)
a1.normalVar = 10   -- 修改成员变量
a1:NormalMethod()   -- 调用成员函数
a2:NormalMethod()

A:StaticFunc()  -- 通过类名调用静态函数
a1:StaticFunc() -- 通过对象调用静态函数

输出如下:

text 复制代码
normalVar is 10
normalVar is 2
staticVar is 0
staticVar is 0

最后补充一个讨论,调用时这两种写法等价:

Lua 复制代码
a1:NormalMethod()   -- 调用普通方法
a1.NormalMethod(a1) -- 等价于上述写法

但是显然第二种写法危险得多,因为可能第二个a1会拼写错误。

类继承

虽然lua不鼓励大家写继承,但是还是能写的。

对于单继承的情况,将子类的元表设置成基类即可。例如:

Lua 复制代码
setmetatable(B, A) -- B 继承了 A

示例如下:

Lua 复制代码
A = {             -- 基类名为 A
    staticVar = 0 -- 静态变量
}
A.__index = A     -- 当做格式即可


function A.StaticFunc()                   -- 静态函数
    print("staticVar is " .. A.staticVar) -- 可以访问静态变量
end

function A:New(number) -- 定义构造函数,使用其它名称也是可以的
    -- self 类似 this 指针
    local obj = {}
    setmetatable(obj, self)     -- 将对象 obj 的元表设置为类 A
    obj.normalVar = number or 0 -- 使用 or 来制定默认值
    return obj
end

function A:NormalMethod()                    -- 成员函数
    print("normalVar is " .. self.normalVar) -- 可以访问成员变量
end

B = {}             -- 继承类名为 B
B.__index = B      -- 当做格式即可
setmetatable(B, A) -- B 继承了 A


function B:New(number)               -- 定义构造函数,使用其它名称也是可以的
    -- self 类似 this 指针
    local obj = A:New(number)        -- 使用基类的构造函数
    setmetatable(obj, self)          -- 将对象 obj 的元表设置为类 B
    obj.normalVar2 = number + 1 or 0 -- 使用 or 来制定默认值
    return obj
end

function B:NormalMethod2()                     -- 成员函数
    print("normalVar2 is " .. self.normalVar2) -- 可以访问成员变量
end

local b = B:New(1) -- 调用构造函数来创建对象
b.normalVar = 10   -- 修改成员变量
b:NormalMethod()   -- 调用成员函数
b.normalVar2 = 11
b:NormalMethod2()
b.StaticFunc() -- 可以通过派生类对象访问基类的静态函数

输出如下:

text 复制代码
normalVar is 10
normalVar2 is 11
staticVar is 0

覆盖

另外,由于__index寻址的问题,子类的同名函数会覆盖基类的函数。例如:

Lua 复制代码
A = {             -- 基类名为 A
    staticVar = 0 -- 静态变量
}
A.__index = A     -- 当做格式即可


function A:New(number) -- 定义构造函数,使用其它名称也是可以的
    -- self 类似 this 指针
    local obj = {}
    setmetatable(obj, self)     -- 将对象 obj 的元表设置为类 A
    obj.normalVar = number or 0 -- 使用 or 来制定默认值
    return obj
end

function A:NormalMethod()                    -- 成员函数
    print("normalVar is " .. self.normalVar) -- 可以访问成员变量
end

B = {}             -- 继承类名为 B
B.__index = B      -- 当做格式即可
setmetatable(B, A) -- B 继承了 A


function B:New(number)               -- 定义构造函数,使用其它名称也是可以的
    -- self 类似 this 指针
    local obj = A:New(number)        -- 使用基类的构造函数
    setmetatable(obj, self)          -- 将对象 obj 的元表设置为类 B
    obj.normalVar2 = number + 1 or 0 -- 使用 or 来制定默认值
    return obj
end

function B:NormalMethod()                      -- 成员函数
    print("normalVar2 is " .. self.normalVar2) -- 可以访问成员变量
end

local b = B:New(1) -- 调用构造函数来创建对象
b:NormalMethod()   -- 调用成员函数

输出结果为:

text 复制代码
normalVar2 is 2

而不是:

text 复制代码
normalVar is 1
相关推荐
钟智强16 天前
CVE-2025-49844高危预警:Redis Lua脚本引擎UAF漏洞深度剖析与POC实战
数据库·redis·web安全·junit·lua
闲人编程16 天前
聚合管道与复杂查询
开发语言·oracle·lua·match·查询·聚合·lookup
会周易的程序员17 天前
cNetgate物联网网关内存数据表和数据视图模块架构
c语言·c++·物联网·架构·lua·iot
会周易的程序员18 天前
cNetgate插件架构设计详解 动态库 脚本二开lua, python, javascript
javascript·c++·python·物联网·lua·iot
白太岁22 天前
Redis:(3) Lua 与 Redis、基于连接池的 Facade 模式封装
数据库·c++·redis·lua·外观模式
Maguyusi1 个月前
go 批量生成c++和lua proto文件
c++·golang·lua·protobuf
foxsen_xia1 个月前
Kamailio通过Lua写路由
开发语言·lua·信息与通信
码农周1 个月前
nginx + Lua 实现域名访问日志统计
nginx·lua
難釋懷1 个月前
Lua脚本解决多条命令原子性问题
开发语言·lua
AI_56781 个月前
Postman接口测试提速技巧:批量请求+智能断言实践
测试工具·lua·postman