【lua中继承的理解】

我们都知道类具有抽象、封装,继承、多态等特性。
lua中的数据集合都是以表的形式呈现,一个table就是一个类。

而lua中继承的实现以元表和元方法来实现。

下面看下lua中类的简单实现:

---创建类
---@param className string 类名
---@param superClass table|function|nil Class 父类
function Class(className, superClass)
    local clazz = {}
    clazz._className = className
    local superType = type(superClass)

    if superType == "function" or superType == "table" then
        setmetatable(clazz,{__index = superClass})		--实现继承的关键代码
        clazz._super = superClass
    else
        clazz.Ctor = function ()  end 		--提供一个默认的构造函数
    end

    function clazz.New(...)
        local instance = {}
        setmetatable(instance,{__index = clazz})		--实现:类的实例访问类的字段或函数
        instance._class = clazz
        instance:Ctor(...)
        return instance
    end

    return clazz
end

local A = class("A")    --实现一个A类

local B = class("b", A)   -- B继承A

- 注意:
---------类的实现例子中可以看出,实际上就是两张表的表现,类模板表:clazz ,实例对象表:instance,后续的一切操作都基于这两张表。

这里不得不提一下lua中的 “.” 和 “:”,其中 . 是提取表中元素方法; :在提取表元素的同时,会传递当前作用域。
如定义表方法时:
A.Ctor(A, …)
等同 A:Ctor(…)

下面通过几个例子深入理解一下
示例1:

	local A = class("A")
	function A:ctor(i)
		self.tb = i    
	end

	 local ins_1 = A.new(2)
	 local ins_2 = A.new(3)
	-- A:ctor(1)	
	 print("zxf ======  ".. A.tb)
	 print("zxf ======  ".. ins_1.tb)
	 print("zxf ======  ".. ins_2.tb)

上面说过,lua中的类就是两张表,模板表(clazz)和实例表(instance),这里分别赋值给了 A 和 ins_1、ins_2。

之后分别打印三张表中的属性tb, 两个实例ins_1、ins_2都能正常打印,A.tb报错提示属性为空不存在。

原因在于   :
实例使用了A表的new方法创建一个实例并返回,
new方法中:
		 instance:Ctor(...)
相当于ins_1:Ctor(...)
	  ins_1.Ctor(ins_1, ...)
所以,实例中存在了tb属性。
而A表只存在Ctor方法,并未执行,所以并不存在tb属性,将注释A:Ctor(1)释放,即可打印出A的tb属性。

示例2
深入理解了这个示例,也就清楚了lua继承的使用,也就是几张表与作用域的关联

	-- 元表继承的理解
	local A = class("A")
	function A:ctor(i)
		self.tb = i
	end

	local B = class("B", A)
	function B:ctor(i)
		self.super.ctor(self,i)
	end

   -- 打印A表属性tb
	A:ctor(1)
	B.super:ctor(1)
	B.super.ctor(A, 1)   -- 这种写法有点多余
	print("zxf ======  ".. A.tb)

    -- 打印B表属性tb
	B:ctor(2)
	B.ctor(B,2)
	A.ctor(B,2)
	print("zxf ======  ".. B.tb)

	-- 打印A类实例属性tb
	local ins_1 = A.new(3)
	print("zxf ======  ".. ins_1.tb)

	-- 利用A实例打印A表属性tb
	local ins_1 = A.new(3) -- 这里必须要设置,才能区分ins_1表、A表自己的值,不然会顺着元表自动找值(元表的特性),导致打印的都是A表的属性tb
	ins_1.ctor(A,5)   -- 不必要的写法  完全等同于 A:ctor(5)
	print("zxf ======  ".. ins_1.tb)

	-- 打印B类实例属性tb
	local ins_B_1 = B.new(5)
    local ins_B_2 = B.new(6)
	print("zxf ======  ".. ins_B_1.tb)
	print("zxf ======  ".. ins_B_2.tb)

	-- 利用B类实例打印B类属性tb
	local ins_B_1 = B.new(5)
	B:ctor(50)  
	-- 实例和B表  必须要设置,才能区分ins_B_1表、B表、A表自己的值,不然会顺着元表自动找值(元表的特性),导致打印的都是A表的属性tb

	ins_B_1.super:ctor(100)    --B类实例中不存在super,会去元表B中找,找到super,而ins_B_1.super == A,所以这里执行的是A:ctor(100)
	print("zxf ======  ".. ins_B_1.tb)
	print("zxf ======  ".. B.tb)
	print("zxf ======  ".. A.tb)

	ins_B_1.super.ctor(B, 78)   -- 使用A表方法更改B表的属性tb
	A.ctor(B, 78)
	print("zxf ======  ".. B.tb)
	print("zxf ======  ".. A.tb)

看懂了美~~~

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值