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
相关推荐
利来利往4 天前
【ai写代码】lua-判断表是否被修改
lua
陈天cjq4 天前
Redis 实用型限流与延时队列:从 Lua 固定/滑动窗口到 Streams 消费组(含脚本与压测)
redis·junit·lua
Warren984 天前
Lua 脚本在 Redis 中的应用
java·前端·网络·vue.js·redis·junit·lua
柯南二号5 天前
MacOS 系统计算机专业好用工具安装
开发语言·lua
神洛华5 天前
Lua语言程序设计2:函数、输入输出、控制结构
开发语言·lua
测试界清流9 天前
Postman接口测试入门
开发语言·lua
Volunteer Technology10 天前
Lua基础+Lua数据类型
开发语言·junit·lua
Volunteer Technology10 天前
openresty-lua-redis案例
redis·lua·openresty
WaterRun13 天前
开源项目luaToEXE: 将.lua封装为自带解释器无lua环境依赖的可执行文件工具
lua
William一直在路上13 天前
LUA脚本语言
开发语言·lua