Lua没有严格的oo(Object-Oriented)定义,可以利用元表特性来实现。我
08月27日 14:37
Lua 没有严格的 oo(Object-Oriented)定义,可以利用元表特性来实现
先定义所有类的基类,即Object
类。代码顺序从上到下,自成一体。完整代码
定义一个空表 Object
,__index
指向其自身(继承将直接使用该表作为对象的元表)
(相关资料图)
Object = {}Object.__index = Object
new
定义构造对象时的初始化行为,相当于构造器。基类不需要进行任何初始化操作
function Object:new()end
extend
实现了类继承,具体流程
cls
,作为类__index
指向其自身(子类可被继承)(覆盖了父类复制给子类的 __index
)super
字段指向父类function Object:extend() local cls = {} for k, v in pairs(self) do if k:find("__") == 1 then cls[k] = v end end cls.__index = cls cls.super = self setmetatable(cls, self) return clsend
implement
用于实现接口类,可传入多个接口
cls
function Object:implement(...) for _, cls in pairs({ ... }) do for k, v in pairs(cls) do if self[k] == nil and type(v) == "function" then self[k] = v end end endend
is
用于判断某个类或对象实例是否是另一个类
function Object:is(T) local mt = getmetatable(self) while mt do if mt == T then return true end mt = getmetatable(mt) end return falseend
__tostring
用于对象 print
或 tostring
时自定义字符串化
function Object:__tostring() return "Object"end
直接用类名称,来实现一个对象的实例化。__call
可以把变量当函数使用,比如Car
类(变量),local mycar = Car()
,生成了一个对象实例myCar
,属于类Car
__index
也就是去父类找function Object:__call(...) local obj = setmetatable({}, self) obj:new(...) return objend
全局函数 unrealized
用于模拟接口或抽象类未定义的方法,子类未实现时会寄
function unrealized(...) error("未实现", 2)end
到现在为止已经模拟了一个单继承OO,在需要的地方导入模块,使用 Object
和 unrealized
这两个全局变量
接下来实现抽象工厂模式。抽象工厂能创建一系列相关的对象,而无需指定其具体类。
考虑如下情况,有多类敌人(正方形、圆形、长条),敌人初始化是两种状态的一种(正常状态,厚血状态),且后期敌人和状态种类还会增多
我们先定义敌人抽象类
Enemy = Object:extend()Enemy.draw = unrealizedEnemy.new = function(self) self.hp = 100end
然后定义继承抽象类Enemy
的抽象类SquareEnemy
,与继承抽象类SquareEnemy
的两个普通类SquareEnemyWhite
、SquareEnemyRed
。圆形敌人跟长条敌人同理。
SquareEnemy = Enemy:extend()SquareEnemy.new = function(self, x, y, w) SquareEnemy.super.new(self) self.x = x self.y = y self.w = wendSquareEnemyWhite = SquareEnemy:extend()SquareEnemyWhite.draw = function(self) love.graphics.setColor(1, 1, 1) love.graphics.rectangle("fill", self.x, self.y, self.w, self.w)endSquareEnemyRed = SquareEnemy:extend()SquareEnemyRed.new = function(self, ...) SquareEnemyRed.super.new(self, ...) self.hp = 200endSquareEnemyRed.draw = function(self) love.graphics.setColor(1, 0, 0) love.graphics.rectangle("fill", self.x, self.y, self.w, self.w)end
定义工厂接口,在这里接口算是一种特殊的抽象类(由于只能用表来模拟接口,所以让接口也继承Objcet)
IFactory = Object:extend()IFactory.circleEnemy = unrealizedIFactory.squareEnemy = unrealizedIFactory.barEnemy = unrealized
分别实现白色工厂和红色工厂(如果没有额外的创建操作,可以不用return)
WhiteFactory = Object:extend()WhiteFactory:implement(IFactory)WhiteFactory.circleEnemy = function(...) return CircleEnemyWhite(...)endWhiteFactory.squareEnemy = function(...) return SquareEnemyWhite(...)endWhiteFactory.barEnemy = function(...) return BarEnemyWhite(...)endRedFactory = Object:extend()RedFactory:implement(IFactory)RedFactory.circleEnemy = function(...) return CircleEnemyRed(...)endRedFactory.squareEnemy = function(...) return SquareEnemyRed(...)endRedFactory.barEnemy = function(...) return BarEnemyRed(...)end
接下来测试抽象工厂
require "oo"require "enemy.aac"require "enemy.bar"require "enemy.circle"require "enemy.square"require "factory.aac"require "factory.red_factory"require "factory.white_factory"enemies = {}love.load = function() IFactory = WhiteFactory() table.insert(enemies, IFactory.circleEnemy(100, 100, 25)) table.insert(enemies, IFactory.squareEnemy(100, 200, 25)) table.insert(enemies, IFactory.barEnemy(100, 300, 10, 50)) IFactory = RedFactory() table.insert(enemies, IFactory.circleEnemy(200, 100, 25)) table.insert(enemies, IFactory.squareEnemy(200, 200, 25)) table.insert(enemies, IFactory.barEnemy(200, 300, 10, 50)) for _, enemy in pairs(enemies) do print(enemy.hp) endendlove.draw = function() for _, enemy in ipairs(enemies) do enemy:draw() endend
oo.lua
Object = {}Object.__index = Objectfunction Object:new()endfunction Object:extend() local cls = {} for k, v in pairs(self) do if k:find("__") == 1 then cls[k] = v end end cls.__index = cls cls.super = self setmetatable(cls, self) return clsendfunction Object:implement(...) for _, cls in pairs({ ... }) do for k, v in pairs(cls) do if self[k] == nil and type(v) == "function" then self[k] = v end end endendfunction Object:is(T) local mt = getmetatable(self) while mt do if mt == T then return true end mt = getmetatable(mt) end return falseendfunction Object:__tostring() return "Object"endfunction Object:__call(...) local obj = setmetatable({}, self) obj:new(...) return objendfunction unrealized(...) error("未实现", 3)end-- return Object
QUESTION1
如果不复制元方法,假设类B继承类A,类B的对象实例b,b的元表是类B,在调用 b + b 时,涉及到算术运算符相关的元方法,b会在父类B中查找__add
,找不到并不会顺着B的元表__index
再去B的父类A找,因此会报错
A = { __index = A, __add = function(a, b) return a.age + b.age end, name = "小白"}B = { __index = B, }b = { __index = b, age = 1 }setmetatable(B, A)setmetatable(b, B)print(b.name)print(b + b)--[[> dofile "TEST/test.lua"小白TEST/test.lua:15: attempt to perform arithmetic on a table value (global "b")stack traceback: TEST/test.lua:15: in main chunk [C]: in function "dofile" stdin:1: in main chunk [C]: in ?]]
点我返回
关键词:
Lua没有严格的oo(Object-Oriented)定义,可以利用元表特性来实现。我
08月27日 14:37
诺德斯特龙公司第二财季营收和每股收益均超出预期。然而,该公司本季度
08月27日 14:48
受日本核污染水排海影响,24日,我国部分区域发生食盐抢购现象。对此,
08月27日 14:38
CBA历史上有很多优秀的大外援,比如布拉切,比如积臣。但要论个人能力
08月27日 14:44
8月24日,中盐集团发布关于保障食盐市场供应的声明,全文如下:受日本
08月27日 14:46
来源:经济参考报作者:王璐 7月完成营业性客运量9 1亿人次,同比增
08月27日 14:43
中新社莫斯科8月24日电俄罗斯总统普京24日向发生在特维尔州的飞机失事
08月27日 14:36
8月24日,第十四届中国—东北亚博览会进入第二天。而在这些亮点中,位
08月27日 14:43
为发扬中华优秀传统文化,传承七夕节日习俗,8月24日,张沟镇新时代文
08月27日 14:33
统计数据分析方法包括哪些,统计数据分析方法这个很多人还不知道,现在
08月27日 14:37
注意事项1 请各位应聘者认真阅读岗位要求,完整填写并提交简历。如因个
08月27日 14:33
瑞联新材公告,拟以5000万元-8000万元回购公司股份,回购价格不超过51
08月27日 14:29
据中国驻日本大使馆官方网站消息,8月24日,驻日本大使吴江浩就日方启
08月27日 14:38
问:2023年郑州9月方特梦幻王国营业时间是什么?答:郑州方特梦幻王国9
08月27日 14:42
大家好,小康来为大家解答以上问题。三个香怎么读,三个香很多人还不知
08月27日 14:32
◎记者注意到,七匹狼的销售增长贡献主要源于直营,而其线上销售增长疲
08月27日 14:33
泰山队遭遇日本冠军和韩国杯赛冠军,亚冠分组:C罗、内马尔所在的球队
08月27日 14:34
我是小前,我来为大家解答以上问题。葡萄品种排名前十,葡萄品种很多人
08月27日 14:35
,你们好,今天0471房产来聊聊一篇多成,多成简述的文章,网友们对这件
08月27日 14:32
浙商证券股份有限公司刘雯蜀,郑毅近期对深桑达A进行研究并发布了研究报
08月27日 14:27
今年6月以来,甘肃省河西走廊大部、中部及南部局地发生旱情并持续发展。
08月27日 14:30
机器人在投资者互动平台表示,公司核应急机器人可应用于核工业放射性环
08月27日 14:27
8月23日,记者从国家药品监督管理局(NMPA)获悉,由迪哲(江苏)医药
08月27日 14:36
数据显示,咖啡消费市场进一步下沉,小镇咖啡热度不断高涨,消费新业态
08月27日 14:25
核心观点:中国经济网评论员子房先生认为,网约车市场已从早前的“烧钱
08月27日 14:34
不过接受《环球时报》记者采访的专家认为,法国的相关政策主要是从产业
08月27日 14:27
补填盲点仍然是早餐民心工程的重头戏。记者昨天在市商务委“政府开放月
08月27日 14:27
10月11日晚间,*ST盐湖公告,公司收到青海省西宁市中级人民法院(以下简
08月27日 14:23
成武县气象台2023年08月26日15时40分发布暴雨黄色预警信号:受西南涡影
08月27日 14:35
格隆汇8月23日丨百诚医药(301096 SZ)公布,公司董事会于2023年8月22日
08月27日 14:27