当前位置: 首页 > news >正文

Lua(面向对象)

Lua 面向对象基础

Lua 本身没有内置的面向对象(OOP)特性,但可以通过表和元表(metatable)模拟实现。核心是通过 __index 元方法实现继承和多态,通过函数重定义实现方法重写。


继承的实现

Lua 的继承基于原型链。通过将父类作为子类元表的 __index 字段,实现属性查找的链式传递。

-- 父类
local Parent = {}
function Parent:new(name)local obj = { name = name }setmetatable(obj, { __index = Parent })return obj
end
function Parent:say()print("Parent says:", self.name)
end-- 子类继承
local Child = {}
function Child:new(name, age)local obj = Parent:new(name)  -- 调用父类构造函数obj.age = agesetmetatable(obj, { __index = Child })return obj
end-- 设置子类的父类(原型链)
setmetatable(Child, { __index = Parent })

关键点

  • 子类通过 Parent:new() 初始化父类属性。
  • 子类元表的 __index 指向自身,而子类本身的元表 __index 指向父类,形成链式查找。

多态的实现

多态通过方法重写和动态查找实现。子类可以覆盖父类方法,调用时根据实际对象的元表决定执行哪个方法。

-- 子类重写父类方法
function Child:say()print("Child says:", self.name, "age:", self.age)
end-- 测试多态
local parent = Parent:new("Alice")
local child = Child:new("Bob", 10)
parent:say()  -- 输出: Parent says: Alice
child:say()   -- 输出: Child says: Bob age: 10

说明

  • child:say() 优先调用子类的方法,若子类未定义则通过 __index 查找父类方法。

方法重写

直接覆盖父类方法即可实现重写。若需调用父类方法,需显式通过父类引用。

function Child:say()-- 调用父类方法Parent.say(self)-- 扩展子类逻辑print("Extra info:", self.age)
end

注意

  • 使用 Parent.say(self) 而非 Parent:say(),需手动传入 self 以保持对象上下文。

完整示例代码

-- 父类
local Parent = {}
function Parent:new(name)local obj = { name = name }setmetatable(obj, { __index = Parent })return obj
end
function Parent:say()print("Parent says:", self.name)
end-- 子类
local Child = {}
function Child:new(name, age)local obj = Parent:new(name)obj.age = agesetmetatable(obj, { __index = Child })return obj
end
setmetatable(Child, { __index = Parent })-- 重写方法
function Child:say()Parent.say(self)  -- 调用父类方法print("Child added:", self.age)
end-- 测试
local child = Child:new("Tom", 8)
child:say()

封装实现方式

封装的核心在于将数据和操作数据的方法绑定,并控制外部访问权限。Lua中通过闭包或表结合元表实现:

闭包实现私有性

function createObject()local privateData = 0local obj = {}function obj:getData()return privateDataendfunction obj:setData(value)privateData = valueendreturn obj
end

这种方式利用局部变量保持私有状态,外部无法直接访问privateData

表结合元表的封装

local Account = {}
Account.__index = Accountfunction Account.new(balance)local obj = {_balance = balance or 0  -- 约定下划线开头表示私有}setmetatable(obj, Account)return obj
endfunction Account:deposit(amount)self._balance = self._balance + amount
end

尽管Lua无法强制私有,但通过命名约定(如_前缀)提示字段不应被外部直接访问。

抽象的实现方法

抽象指隐藏复杂实现细节,仅暴露必要接口。Lua中通过模块化设计实现:

模块作为抽象单元

local abstractModule = {}function abstractModule.complexOperation(a, b)local result = a + b  -- 隐藏具体计算过程-- 其他内部处理...return result
endreturn abstractModule

接口模拟

local interface = {requiredMethod = function() error("Not implemented") end
}function interface.check(obj)for k, v in pairs(interface) doif type(v) == "function" and not obj[k] thenerror("Missing required method: "..k)endend
end

通过运行时检查确保对象实现了必要方法。

实际应用建议

对于需要更严格封装的场景,可结合闭包和表:

function StrictObject()local data = {}local methods = {}methods.get = function(key) return data[key] endmethods.set = function(key, value) data[key] = value endreturn methods
end

面向对象设计在Lua中是灵活的,应根据项目需求选择合适的实现方式。游戏开发中常用表+元表的方式,而需要严格隐藏细节时更适合闭包方案。

http://www.dtcms.com/a/297667.html

相关文章:

  • 深度学习水论文:特征提取
  • NBIOT模块 BC28通过MQTT协议连接到EMQX
  • 如何在 Ubuntu 24.04 或 22.04 上安装和使用 GDebi
  • 智能网关:物联网时代的核心枢纽
  • ABP VNext + Razor 邮件模板:动态、多租户隔离、可版本化的邮件与通知系统
  • 智能网关芯片:物联网连接的核心引擎
  • 酷暑来袭,科技如何让城市清凉又洁净?
  • 制造业低代码平台实战评测:简道云、钉钉宜搭、华为云Astro、金蝶云·苍穹、斑斑低代码,谁更值得选?
  • 使用 FFmpeg 实现 RTP 音频传输与播放
  • 【Redis】初识Redis(定义、特征、使用场景)
  • Spring框架
  • 认识编程(3)-语法背后的认知战争:类型声明的前世今生
  • vue3单页面连接多个websocket并实现断线重连功能
  • 机器学习笔记(三)——决策树、随机森林
  • Git指令
  • git将本地文件完和仓库文件目录完全替换-------还有将本地更新的文件放到仓库中,直接提交即可
  • C# WPF 实现读取文件夹中的PDF并显示其页数
  • STM32与ADS1220多通道采样数据
  • vscode 登录ssh记住密码直接登录设置
  • GPU 服务器ecc报错处理
  • 详谈OSI七层模型和TCP/IP四层模型以及tcp与udp为什么是4层,http与https为什么是7层
  • SQL 查询与自定义管理工具设计:释放数据底层价值
  • linux C — udp,tcp通信
  • Docker技术入门与实战(附电子书资料)
  • 第七章 愿景10 小杨的立项课
  • 【Practical Business English Oral Scene Interpretation】入职面试No.8~9
  • [NLP]UPF+RTL联合仿真的VCS命令及UPF-aware 波形工具的使用
  • 练习实践-基础设施-文件共享-windows和linux之间的文件共享-smb服务搭建
  • 开发笔记 | 优化对话管理器脚本与对话语音的实现
  • Day 21: 常见的降维算法