LUA中的面向对象

一、元表

在认识lua中的面向对象前,首先要了解元表的概念。

元表使table之间有了父子的概念,当我们子表进行一些特定操作时,会执行元表中的内容。

1.__tostring与__index

print("--元表操作--")
meta = {
	--当子表被当作字符串调用时,会默认执行tostring函数
	__tostring = function(t)
		return t.name
	end,
	--当子表被当作一个函数使用时,会默认call函数
	__call = function(a,b)
		print(a)
		print(b)
		print("子表被当作函数使用")
	end
}
mytable = {
	name = '我是子表'
}
setmetatable(mytable,meta)--设置元表
print(mytable)
mytable(666);

        可以发现当子表被当作函数使用时,也可以传递参数,其中第一个参数默认为自身,后面的参数可通过调用子表函数时传入。

2.运算符重载

        利用运算符重载,我们可以直接对两表进行+ - * /等操作,同时也可以进行 = < 等比较。

        例如在下面代码中我们可以在__add函数中定义返回值(即定义加法的操作)

print('--运算符重载--')
meta2 = {
	--使用+时调用add
	__add = function(n1,n2)
		return n1.num_2 + n2.num
	end
	--其他还有 - sub;* mul;/ div;% mod;^ pow;== eq;< lt;<= le;.. concat
}
mytable2_1 = {
	num = 1,
	num_2 = 2
}
mytable2_2 = {
	num = 2
}
setmetatable(mytable2_1,meta2)
setmetatable(mytable2_2,meta2)
print(mytable2_1+mytable2_2)

3.__index指定与__newindex

        当子表找不到某一属性时,会自动到__index指定的表中寻找。

print('--指定操作__index')
meta3 = {
	age = 1
}
--当子表中找不到某一属性时,回到index指定的表中找属性
meta3.__index = meta3

mytable3 = {}
setmetatable(mytable3,meta3)
print(mytable3.age)
--当赋值时,如果赋值一个不存在的索引,那么会把这个值赋到newindex所指的表中
meta3.__newindex = {}
mytable3.number = 3
print(mytable3.number)--此时新定义的number在__newindex指定的新表中
print(meta3.__newindex.number)

4.其他操作

--获取元表
print(getmetatable(mytable3))
--查看自身是否有属性
print(rawget(mytable3,'age'))
--绕过newindex 直接设置自身变量
rawset(mytable3,'age',6)
print(mytable3.age)

二、面向对象

创建一个表table充当类

Object = {
	num = 1,

	fun = function()
		print("这是父类")
	end
}

        1.封装

        通过__index指向本身,完成类的初始化创建

--------封装-------------
function Object:new()
	local obj = {}

	self.__index = self
	setmetatable(obj,self)
	return obj
end

obj = Object:new()
print(obj.num)

        输出结果为:1

        2.继承

        这里主要是通过新建一个表(可以看作类),并同样为它执行元表创建与__index的指定操作来实现继承。有点类似封装,但这里是创建一个新表。(该例子中采用大G表进行对子类的创建)

--------继承-------------
print("继承")
function Object:subClass(className)
	_G[className] ={}

	local obj = _G[className]
	self.__index = self
	obj.base = self
	setmetatable(obj,self)
end

Object:subClass('son')
print(son.num)
son.fun()

输出结果:1
                  这是父类

        3.多态

        在下面的例子中gameobject充当player的父类,并在父类中定义一个test函数,而要实现多态只需在子类中对父类函数进行重写即可。同时也可以看到上述的封装与继承也可以正常使用。

        此外,这里在重写父类函数时存在一个坑点,因此我们在执行父类逻辑时,最好不用冒号而是用点然后自己传参数,具体原因可通过下方代码注释理解。

--------多态-------------
print("多态")
Object:subClass("gameObject")
function gameObject:test()
	-- body
	print("父类test函数")
end

gameObject:subClass("player")
function player:test()
	--保留父类
	--坑点:这种方法若还有另一个子类p2也执行了修改变量的操作,则修改的变量都是父类的变量
	--换而言之就是两个子类间的修改变量的操作会相互影响
	--因此执行父类逻辑时,最好不用:而是用. 然后自己传参数
	--self.base:test()
	--正确的方式
	self.base.test(self)

	print("子类test函数")
end

local p1 = player:new()
p1:test()

输出结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值