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
相关推荐
疯狂吧小飞牛17 小时前
Lua C API 中的 lua_rawseti 与 lua_rawgeti 介绍
c语言·开发语言·lua
半夏知半秋17 小时前
lua对象池管理工具剖析
服务器·开发语言·后端·学习·lua
爬山算法17 小时前
Redis(63)Redis的Lua脚本如何使用?
redis·junit·lua
疯狂吧小飞牛1 天前
Lua 中的 __index、__newindex、rawget 与 rawset 介绍
开发语言·junit·lua
疯狂吧小飞牛1 天前
Lua C API 中的注册表介绍
java·c语言·lua
爬山算法1 天前
Redis(64)Redis的Lua脚本有哪些常见场景?
数据库·redis·lua
疯狂吧小飞牛1 天前
Lua C API 中一段LUA建表过程解释
c语言·junit·lua
疯狂吧小飞牛1 天前
Lua中,表、元表、对象、类的解析
开发语言·junit·lua
❀͜͡傀儡师1 天前
OpenResty + Lua + Redis 鉴权案例,适用于 x86 和 ARM 架构的 Docker 环境。
redis·lua·openresty
柳贯一(逆流河版)2 天前
Redis 分布式锁实战:解决马拉松报名并发冲突与 Lua 原子性优化
redis·分布式·lua