LuaObject = {}
function LuaObject.extends(o)
o = o or {}
local obj = {}
setmetatable(obj, {
__index = o
})
return obj
end
local function LuaObjectClone(obj, objMap)
if not obj or type(obj) ~= "table" and type(obj) ~= "userdata" then
print(string.format("传入对象类型【%s】,请传入Lua表对象", type(obj)))
return nil
end
local newObj = {}
if not objMap then
objMap = {}
end
-- local newMeta = {}
-- if not objMap then
-- objMap = {}
-- end
local meta = getmetatable(obj)
if meta then
local metaNew = {}
for key, value in pairs(meta) do
if type(value) == "table" or type(value) == "userdata" then
local newtb = LuaObjectClone(value, nil)
metaNew[key] = newtb
else
metaNew[key] = value
end
end
setmetatable(newObj, metaNew)
end
for key, value in pairs(obj) do
if type(value) == "table" or type(value) == "userdata" then
local tbTemp = objMap[tostring(value)]
if not tbTemp then -- 如果要拷贝的table不是当前table或者没有拷贝过的类才能拷贝,否则直接赋值(因为已经拷贝了)
local tb = LuaObjectClone(value, objMap)
objMap[tostring(value)] = tb -- 存储当前已拷贝的table ,防止类相互嵌套死循环
newObj[key] = tb
else
newObj[key] = value
end
else
newObj[key] = value
end
end
return newObj
end
function LuaClone(obj)
return LuaObjectClone(obj)
end
function LuaNew(obj)
if not obj or type(obj) ~= "table" and type(obj) ~= "userdata" then
print(string.format("传入对象类型【%s】,请传入Lua表对象", type(obj)))
return nil
end
local tb = Extends(obj)
return LuaObjectClone(tb)
end
local metatableLuaObject = {
__call = function(_, newTb)
if not newTb or type(newTb) ~= "table" and type(newTb) ~= "userdata" then
print(string.format("传入对象类型【%s】,请传入Lua表对象", type(newTb)))
return nil
end
local obj = {}
local newTable = {
Base = newTb,
membersMap = {},
Clone = function()
return LuaObjectClone(obj)
end
}
local metatable = {
__index = function(bt, name) -- 访问继承类不存在的此字段时调用
if type(newTb) == "userdata" then
local member = newTb[name]
if not member then
print(string.format("<color=#ff0000ff>用户数据,获取此【%s】成员不存在</color>",
name))
end
if type(member) == "function" then
return function(self, ...) -- 替换:语法糖的self
member(newTb, ...)
end
end
else
return newTb[name]
end
end
}
setmetatable(newTable, metatable)
local basemetabable = {
__index = newTable,
__newindex = function(bt, key, value) -- 设置继承类不存在的此字段时调用
if type(key) == "string" and key == "Base" then
print("禁止设置Base字段,此字段为基类,保留字段")
else
if type(value) == "function" or type(value) == "thread" then -- 防止继承类把基类方法覆盖,只有非方法成员才能给基类复制
rawset(bt, key, value)
else
local baseValue = newTb[key]
-- --类型匹配
-- if type(value) ==type(baseValue) then
-- -- body
-- end
if baseValue then
if not value then
if not newTable.membersMap[key] then
newTable.membersMap[key] = key
end
end
newTb[key] = value
else
local memberName =
newTable.membersMap[key] -- 存储基类成员名称 ,保证基类成员完整性,同时确定赋值到基类还是派生类(原因时nil会删除成员)
-- 存储基类成员名称 ,保证基类成员完整性,同时确定赋值到基类还是派生类(原因时nil会删除成员)
-- 存储基类成员名称 ,保证基类成员完整性,同时确定赋值到基类还是派生类(原因时nil会删除成员)
if memberName then
newTb[key] = value
else
rawset(bt, key, value)
end
end
-- if baseValue then --只有基类存在当前值且类型相同时,才能给基类赋值,nil不能给基类存在的值赋值,保证基类完整性
-- if type(baseValue) =="string" then
-- newTb[key]= value or ""
-- elseif type(value) ==type(baseValue) then
-- newTb[key]= value
-- else
-- rawset(bt, key, value)
-- end
-- else
-- rawset(bt, key, value)
-- end
end
end
end
}
setmetatable(obj, basemetabable)
return obj
end
}
local function initExtends()
Extends = {}
setmetatable(Extends, metatableLuaObject)
end
initExtends()
------------------------测试代码-----------------------------------------------
local tb = {
name = "zzg",
number = 111111111,
Info = {
aihao = "game"
}
}
print("-----------------------------------------------------------------------")
local netT = Extends(tb)
netT.NewName = "zzg1"
netT.name = "dddddd"
netT.Base = ""
netT.name =nil
netT.name = "zzg1"
print("----------", netT.NewName)
print("----------", netT.name)
print("----------", tb.name)
print("-----------------------------------------------------------------------")
local tbClone = LuaClone(tb)
print("start ---原始table的name值", tb.name)
print("start ---克隆table的name值", tbClone.name)
print("-----------------------------------------------------------------------")
print("原始table的name值", tb.name)
print("克隆table的name值", tbClone.name)
print("-----------------------------------------------------------------------")
local t = LuaNew(tb)
print(t.name)
local tb = {
a=7,
b = 20,
}
function tb:CL(obj)
self:PR(obj)
end
function tb:PR(str)
print(str..tostring(self.a+self.b))
end
local ex = LuaClone(tb)
ex.a=56
tb:CL("ssddd")
ex:CL("dddddddddd")
return LuaObject
Lua 对象实例化及克隆
1.此脚本提供全局Extends()对象继承接口
如:
local tb = {
name = "zzg",
number = 111111111,
Info = {
aihao = "game"
}
}
print("-----------------------------------------------------------------------")
local netT = Extends(tb)
netT将拥有tb所有成员
- 对象深度克隆
如果对象通过Extends()继承类将会拥有Clone()深度克隆方法
如上面的NetT可以通过NetT.Clone()获得一个新的数据完全一样对象
- 全局的lua对象深度克隆方法LuaClone()
local tbClone = LuaClone(tb)
此方法将克隆tb所有成员,并且相互独立
通过图一日志可以验证
- 全局的lua对象创建方法LuaNew()
此方法将会创建一个继承类并且克隆实例化此对象
local t = LuaNew(tb)
Extends和LuaNew的区别
Extends只是继承基类,如果直接使用此方法获得类,修改基类成员时,所有继承此类的对象都将会被改动。
LuaNew方法具有继承和克隆过程,所有实例化的类都相互独立,改动基类互不影响
6.Base为基类,禁止赋值,通过基类可以访问基类