lua 模拟 OOP 设计 - Version1.1

下面是“技术不够,代码来凑”的环节,我只是个搬运工 – 一切尽在代码、注释中


前一篇我们简单的实现了类似 OOP 的 lua 中的 class 设计:lua __call 测试,模拟 OOP 设计

这一篇,我们将更进一步的完善 lua 中 OOP 的代码:

-- 参考:https://blog.csdn.net/linjf520/article/details/108771189#Custom_splits_ss___233
-- 字符串分割函数
---@param str 要被分割的字符串
---@param split_char 以什么字符分割,注意是:字符
function split(str, split_char)
	assert(str ~= nil, "split.str is nil")
	assert(split_char ~= nil, "split.split_char is nil")
	local ret = {}
	for v in string.gmatch(str, "[^" .. split_char .. "]*") do
		-- print("v:" .. v)
		if v ~= "" then -- pass empty
			-- print("match str : " .. v)
			table.insert(ret, v)
		end
	end
	return ret
end

-- 注册 命名空间与类信息
function register_ns_cls(names, tbl)
	-- print("register_ns_cls(names), names : " .. names)
	-- 分割 namespace & class
	local ns = split(names, ".")
	-- 前置 namespace 层级对象,开始第一个层级的前置父级是 _G
	local pre_level_obj = _G
	local pre_class = ""
	-- 遍历 ns 注册所有 ns 与 class 到 _G
	local levels = #ns - 1
	for i = 1, levels do
		-- 先查看前置对象中是否有该 level 对象
		local level = ns[i]
		local tbl = pre_level_obj[level]
		if tbl == nil then
			-- print("not found : " .. pre_class .. "." .. level .. ", and register it")
			-- 如果没有,就创建一个
			tbl = {}
			-- 注册到前置对象中
			pre_level_obj[level] = tbl
			-- print("_G:" .. tostring(_G) .. ", pre_level_obj:" .. tostring(pre_level_obj) .. ",  tbl : " .. tostring( tbl) .. ", pre_level_obj[level] : " .. tostring(pre_level_obj[level]) .. ", _G[level] : " .. tostring(_G[level]))
		else
			-- 如果有,但又不是 table 类型,那就抛个错误
			assert(type(tbl) == "table", "_G[\"" .. level .. "\"] is not a table")
		end

		pre_class = pre_class .. "." .. level

		-- 然后让当前的 tbl 作为前置对象给下一个注册使用
		pre_level_obj = tbl
	end
	local last_one_level_name = ns[#ns]
	pre_level_obj[last_one_level_name] = tbl
end

-- 调用带继承层级的构造函数
function _call_ctor_inherit(cls, self, ...)
	-- 递归继承的metatable
	local _base_cls = getmetatable(cls)
	if _base_cls then
		print("check inherit ctor, in : " .. _base_cls.__name)
		if _base_cls and _base_cls.__index and type(_base_cls.__index) == "table" then
			_call_ctor_inherit(_base_cls.__index, self)
		end
	end

	-- 如果有构造函数就调用
	-- 这里不要使用 obj.ctor,因为可能会查找到 __index 里面去了,所以使用 rawget 来获取原始对象信息,这就可以绕过 __index 的索引查找
	-- local ctor = obj.ctor
	local ctor = rawget(cls, "ctor")
	if ctor then
		print(cls.__name .. " have ctor")
		ctor(self, ...)
	else
		print(cls.__name .. " have no ctor")
	end
end

-- 类的构造函数原型定义、函数实体
function cls_new(self, ...)
	-- self 是 cls
	print(self.__name .. " __call function, with args : ", ...)
	local new_obj = { __name = self.__name }

	-- 给示例化对象设置类接口元表
	setmetatable(new_obj, self)

	-- 调用带继承层级的构造函数
	_call_ctor_inherit(self, new_obj, ...)

	print("return new_obj.namne :" .. new_obj.__name .. ", new_obj : " .. tostring(new_obj))
	-- 返回创建的对象
	return new_obj
end

-- 模拟 oop 语言 定义一个类,可以指定他的名字字段、和他的基类
function class(name, base_cls)

	print("define class, name : " .. name)

	if base_cls then
		print(name .. " have base_cls : " .. tostring(base_cls.__name))
	else
		print(name .. " have no base_cls")
	end

	-- 类信息 table
	local cls = {}
	-- 类的元表 table
	local mtbl = {}
	-- 给 cls 设置名字
	cls.__name = name
	cls.__index = cls
	-- 给 元表 设置名字
	mtbl.__name = name
	-- 将 元表 设置为基类
	mtbl.__index = base_cls
	-- 设置类似 构造函数的地方
	mtbl.__call = function(self, ...) --[=[self 是 cls]=] return cls_new(self, ...) end
	-- 将 cls 表信息对象的元表应用
	setmetatable(cls, mtbl)

	-- 注册 命名空间与类信息
	register_ns_cls(name, cls)

	-- 注意返回的是一个类
	return  cls
end

可以看到这回,我们的 class 函数会简洁很多

而且还多了几个辅助函数

  • function split(str, split_char) 字符串分割函数,前些篇当中有类似的实现:在 lua 中的正则简单使用 - Custom split(s, ss) - 自定义分割函数
  • function register_ns_cls(names, tbl) 将带有 namespace 命名空间层级的类信息注册到 _G
  • function _call_ctor_inherit(cls, self, ...) 调用 cls 对一个的构造函数
  • function cls_new(self, ...) 构造函数原型、实体的定义

示例1

下面是应用示例:

function define_human_and_tom_cls()
	local HumanCls = class("HumanCls")
	-- 给 HumanCls 添加 ctor 构造函数
	HumanCls.ctor = function(self, ...)
		print("HumanCls.ctor, inst.__name : " .. self.__name)
	end

	local TomCls = class("TomCls", HumanCls)
	-- 给 TomCls 添加 ctor 构造函数
	TomCls.ctor = function(self, ...)
		print("TomCls.ctor, inst.__name : " .. self.__name)
	end
end

function test_new_tom()
	define_human_and_tom_cls()
	if TomCls == nil then
		print("not found TomCls in _G")
		TomCls = _G["TomCls"]
	else
		if TomCls.__call then
			print("TomCls found the new()")
		else
			print("TomCls not found the new()")
		end
	end
	local tom = TomCls("arg1", "arg2")
	print("tom.name : " .. tostring(tom.__name) .. ", tom : " .. tostring(tom))
end

print("=== test_new_tom() ===")
test_new_tom()

输出:

=== test_new_tom() ===
define class, name : HumanCls
HumanCls have no base_cls
define class, name : TomCls
TomCls have base_cls : HumanCls
TomCls not found the new()
TomCls __call function, with args : 	arg1	arg2
check inherit ctor, in : TomCls
check inherit ctor, in : HumanCls
HumanCls have ctor
HumanCls.ctor, inst.__name : TomCls
TomCls have ctor
TomCls.ctor, inst.__name : TomCls
return new_obj.namne :TomCls, new_obj : table: 00B09570
tom.name : TomCls, tom : table: 00B09570

示例2

function test_more_cls()
	-- 下面我们可以把继承层级弄深一些,并且将 .ctor 构造函数值设置一部分,再看看输出信息
	function define_BASE_AND_ABCD_cls()

	end
	local BASE_CLS = class("Base_CLS")
	local CLS_A = class("CLS_A", BASE_CLS)
	local CLS_B = class("CLS_B", CLS_A)
	local CLS_C = class("CLS_C", CLS_B)
	local CLS_D = class("CLS_D", CLS_C)

	-- CLS_A、CLS_D 都不设置构造函数

	CLS_B.ctor = function(self)
		print("CLS_B.ctor run, inst.name : " .. self.__name)
	end
	CLS_C.ctor = function(self)
		print("CLS_C.ctor run, inst.name : " .. self.__name)
	end

	local new_d = CLS_D("arg1", "arg2", "arg3")
	print("new_d.cls__name : " .. new_d.__name)
end

print("=== test_more_cls() ===")
test_more_cls()

输出:

=== test_more_cls() ===
define class, name : Base_CLS
Base_CLS have no base_cls
define class, name : CLS_A
CLS_A have base_cls : Base_CLS
define class, name : CLS_B
CLS_B have base_cls : CLS_A
define class, name : CLS_C
CLS_C have base_cls : CLS_B
define class, name : CLS_D
CLS_D have base_cls : CLS_C
CLS_D __call function, with args : 	arg1	arg2	arg3
check inherit ctor, in : CLS_D
check inherit ctor, in : CLS_C
check inherit ctor, in : CLS_B
check inherit ctor, in : CLS_A
check inherit ctor, in : Base_CLS
Base_CLS have no ctor
CLS_A have no ctor
CLS_B have ctor
CLS_B.ctor run, inst.name : CLS_D
CLS_C have ctor
CLS_C.ctor run, inst.name : CLS_D
CLS_D have no ctor
return new_obj.namne :CLS_D, new_obj : table: 00E5C170
new_d.cls__name : CLS_D

示例3

function test_has_inherit_ns_cls()
	-- 下面注册类型 C# 中的泛型类信息
	print("###### start testing c#-like generic defines ######")
	local System = class("System")
	local Generic = class("System.Generic")
	local List = class("System.Generic.List")
	local Array = class("System.Generic.Array")
	local Stack = class("System.Generic.Stack")
	local Queue = class("System.Generic.Queue")
	-- 下面是注册我自己测试的类信息
	print("###### start testing my ns level & cls defines ######")
	local MyNs1 = class("MyNs1")
	local MyNs2 = class("MyNs1.MyNs2")
	local Custom = class("MyNs1.MyNs2.Custom")
	-- 下面是直接跨层级注册
	print("###### start testing straghtly levels & cls defines ######")
	local MyCustomClass = class("Level1.Level2.Level3.MyCustomClass")
end
function applying_custom_inherit_cls()
	print("###### start testing new levels & cls defines ######")
	local queue_inst = System.Generic.Queue("QueueArg1", "QueueArg2", "QueueArg3")
	local custom_inst = MyNs1.MyNs2.Custom("CustomArg1", "CustomArg2", "CustomArg3")
	local my_custom_inst = Level1.Level2.Level3.MyCustomClass("MyCustomArg1", "MyCustomArg2", "MyCustomArg3")
	print("queue_inst.__name : " .. tostring(queue_inst.__name))
	print("custom_inst.__name : " .. tostring(custom_inst.__name))
	print("my_custom_inst.__name : " .. tostring(my_custom_inst.__name))
end

print("=== test_has_inherit_ns_cls() ===")
test_has_inherit_ns_cls()
applying_custom_inherit_cls()

输出:

=== test_has_inherit_ns_cls() ===
###### start testing c#-like generic defines ######
define class, name : System
System have no base_cls
define class, name : System.Generic
System.Generic have no base_cls
define class, name : System.Generic.List
System.Generic.List have no base_cls
define class, name : System.Generic.Array
System.Generic.Array have no base_cls
define class, name : System.Generic.Stack
System.Generic.Stack have no base_cls
define class, name : System.Generic.Queue
System.Generic.Queue have no base_cls
###### start testing my ns level & cls defines ######
define class, name : MyNs1
MyNs1 have no base_cls
define class, name : MyNs1.MyNs2
MyNs1.MyNs2 have no base_cls
define class, name : MyNs1.MyNs2.Custom
MyNs1.MyNs2.Custom have no base_cls
###### start testing straghtly levels & cls defines ######
define class, name : Level1.Level2.Level3.MyCustomClass
Level1.Level2.Level3.MyCustomClass have no base_cls
###### start testing new levels & cls defines ######
System.Generic.Queue __call function, with args : 	QueueArg1	QueueArg2	QueueArg3
check inherit ctor, in : System.Generic.Queue
System.Generic.Queue have no ctor
return new_obj.namne :System.Generic.Queue, new_obj : table: 00E64758
MyNs1.MyNs2.Custom __call function, with args : 	CustomArg1	CustomArg2	CustomArg3
check inherit ctor, in : MyNs1.MyNs2.Custom
MyNs1.MyNs2.Custom have no ctor
return new_obj.namne :MyNs1.MyNs2.Custom, new_obj : table: 00E64550
Level1.Level2.Level3.MyCustomClass __call function, with args : 	MyCustomArg1	MyCustomArg2	MyCustomArg3
check inherit ctor, in : Level1.Level2.Level3.MyCustomClass
Level1.Level2.Level3.MyCustomClass have no ctor
return new_obj.namne :Level1.Level2.Level3.MyCustomClass, new_obj : table: 00E645A0
queue_inst.__name : System.Generic.Queue
custom_inst.__name : MyNs1.MyNs2.Custom
my_custom_inst.__name : Level1.Level2.Level3.MyCustomClass
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值