在Lua中实现“继承”遇到的坑

  • 在Lua中如何模拟“继承”

方法是通过元表来模拟“继承”。如下所示,先定义一个A作为父类;再实现New方法,该方法主要是将A设置为o的元表,然后返回o;最后将A:New返回的值赋值给B,此时B就是继承于A。在New中有一个关键的一步是self.__index = self,这一步必不可少,原因是当你通过Key来访问表中的值,若表中该Key为nil,那么Lua会寻找元表中__index键;__index键如果是function则会直接执行,若__index键为表,则会在该表中寻找Key值。

A = {}
function A:New()
	local o = {}
	setmetatable(o, self)
	self.__index = self
	return o
end
B = A:New()
  • 在“继承”中该值是想象中的值吗
A = {Num = 1}
function A:New()
	local o = {}
	setmetatable(o, self)
	self.__index = self
	return o
end
B = A:New()
(1)B.Num = 2
(2)B.Num = nil

打印B.Num按照常规的继承思路(1) Num = 2, (2) Num 是一个空值。然而并非如此,(1) Num = 2, (2) Num = 1。其实使用元表不是真正意义上的继承,元表的概念只是简单的将两张表关联起来,通过元方法来表操作两表。B.Num = 2 其实不是操作A表中的Num,而是在B表中新建一个Key叫Num并且赋值为2。B.Num = nil 是将B表中的Num删除,再根据模拟“继承”的理论来推,当B表中的Key为空时,会去寻找元表中__index赋值的表Key的值。

  • 小测验
A = {Num1 = 1}
function A:New()
	local o = {}
	setmetatable(o, self)
	self.__index = self
	o.Num2 = 1
	self.Num3 = 1
	return o
end
B = A:New()
B.Num4 = 1

问:Num1、Num2、Num3、Num4分别属于谁的表

答:Num1、Num3为A表中的Key,Num2、Num4为B表中的值。

故:在模拟“继承”的时候,要格外注意该Key属于谁,在操作谁的Key,当Key为nil的时候,再次使用是否会读取不想要的值

思考:如果Key为nil,元表中同名的Key不nil,使用if判断是否会判空。

  • 在“继承中”函数里的self.Value是谁
A = {Num = 1}
function A:New()
	local o = {}
	setmetatable(o, self)
	self.__index = self
	return o
end
function A:Init()
	self.Num = 2
end
B = A:New()
(1)B:Init()
(2)B.Num = nil

按照上述的思路来看(1)Num = 2, (2)Num = 2。然后并非如此,(1)Num = 2,(2)Num = 1 首先B:Init(),B表没有Init函数,按照上述理论,应该是调用A:Init函数,self.Num = 2是操作A表中Num;这是错误的想法。首先要明确Lua中的:操作符表明了什么,表明了在调用的时候将会调用者传入为self。打印下A,B,A:Init中的self;会发现地址B和self地址相同。所以B:Init()调用时,self是指B。

  • 小测验
A = {Num = 1}
function A:New()
	local o = {}
 	setmetatable(o, self)
 	self.__index = self
 	return o
end
function A:Init(c)
	self.Num = c
end
B = A:New()
C = A:New()
B.Init(C,3)

问:A.Num, B.Num, C.Num 分别是多少

答:A.Num为1, B.Num为1, C.Num为3

故:Lua函数调用中:的操作会默认将调用者传入函数,而B.Init(C,3)是显示的将默认参数给传入C,所以C是self

思考:如果函数直接定义为A.Init效果会如何呢

Lua实现数据持久化通常涉及到将程序运行时的状态信息存储到磁盘或其他非易失媒介上,以便于下次启动时恢复。以下是一些常用的方法: 1. **JSON 或 Lua 的原生格式**:Lua 自带的 `cjson` 模块(对于 LuaJIT 用户)或 `lua-serializable` 等第三方库,可用于序列化 Lua 表到 JSON 格式,然后保存到文件。 ```lua local json = require 'cjson' local data = {name = "example", number = 123} local jsonString = json.encode(data) io.open('data.json', 'w'):write(jsonString) ``` 2. **文本文件**:简单的数据可以直接写入文本文件,每一行表示一条记录,适合小规模数据。 3. **数据库**:如 SQL 或 NoSQL 数据库,如 SQLite,可以使用 Lua 的数据库驱动(luasql 或 sqlite3)来进行数据保存和加载。 ```lua local sqlite3 = require'lsqlite3' local db = sqlite3.open_memory() db:exec[[ CREATE TABLE users ( id INTEGER PRIMARY KEY, name TEXT NOT NULL ); ]] db:execute("INSERT INTO users (name) VALUES (?)", "John Doe") ``` 4. **二进制文件**:对于大型或复杂的数据结构,可能更适合使用二进制格式,如Protocol Buffers或MessagePack。 5. **LuaLUA_CDATA**:可以考虑使用 C API 的 `lua_pushlightuserdata` 和 `lua_getlightuserdata` 来存储原始数据结构,但这种方式不是非常常见,因为这涉及到内存管理与跨平台兼容性。 每种方法的选择取决于你的应用需求,如数据大小、安全性以及是否需要与其他系统交互等因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值