最新要闻
- 北京:9月1日起北京二环主路全线取消公交专用道
- “让你们满意,是我的职责” 记建行浙江温州六虹桥支行大堂经理余闲
- 现货白银向上触及24美元/盎司,为8月2日以来首次,日内涨2.54%
- 定兴县:农技专家指导灾后蔬菜生产
- 水稻、瓜果陆续成熟 金秋时节看广袤大地忙碌丰收景象
- 充电15分钟续航450km,昊铂GT抢先领跑800V超充时代
- 回到清朝当总统(关于回到清朝当总统的基本详情介绍)
- 南极海冰融化严重危及帝企鹅幼鸟
- 多家银行提供精准服务 建立绿色通道 优先满足灾后重建信贷需求
- 西北能源监管局主要负责同志出席西北电网2023年网源协调工作会议
- 新华指数|枣企随行就市 红枣价格指数微幅上行
- 《孤注一掷》票房突破32亿:豆瓣评分跌至6.9
- 华为分布式存储全闪新品重磅发布:降低SSD单盘价格!
- 《甄嬛传》的一处情节“Bug” 隐藏着很多人不知道的冷知识
- 假如吃了核污染的食物 会怎么样?
- 帮我们跳过安卓App广告的李跳跳被杀死了!这合理吗?
手机
![中信建投:黑电行业利润空间广阔 估值具有提升空间](http://www.lygmedia.com/uploadfile/2022/0923/20220923103853871.jpg)
中信建投:黑电行业利润空间广阔 估值具有提升空间
![《星空》全球解锁时间公布!豪华版北京时间9月1日早上8点解锁!](http://www.cnmyjj.cn/uploadfile/2022/0610/20220610113536218.jpg)
《星空》全球解锁时间公布!豪华版北京时间9月1日早上8点解锁!
- 中信建投:黑电行业利润空间广阔 估值具有提升空间
- 《星空》全球解锁时间公布!豪华版北京时间9月1日早上8点解锁!
- 南京再添一处必打卡美食街!“南湖记忆”乐活街区开街啦
- 把握智能化机遇 巩固轻工业优势
- 英特尔14代酷睿曝光:Z790主板马上到来
- iPhone15Pro新增灰色 取代原本的金色
家电
[Lua] 如何模拟单继承OO、实现抽象工厂
所有类的基类 Object
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
用于判断某个类或对象实例是否是另一个类
- 循环拿元表,直到没有为止,最后一个元表一定是 Object
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
参考资料
- 《Lua程序设计·第四版》罗伯托·耶鲁萨林斯希 、第227~241页
其它
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、实现抽象工厂
新加坡的邻居,印尼民丹岛,处处是原生态岛屿的新玩法
中信建投:黑电行业利润空间广阔 估值具有提升空间
马泷齿科递表港交所,三年营收12亿,平均每名牙医年入240万
“让村民群众有依靠”(党旗在基层一线高高飘扬)
黔西南州民宗委:形式多样深入开展铸牢中华民族共同体意识培训
北京:9月1日起北京二环主路全线取消公交专用道
“让你们满意,是我的职责” 记建行浙江温州六虹桥支行大堂经理余闲
基金公司中报亮相:华夏基金净利超10亿元,东兴基金利润增幅超600%
现货白银向上触及24美元/盎司,为8月2日以来首次,日内涨2.54%
李红军调研指导老旧小区改造工作
中国驻日大使就福岛核污染水排海向日本政府提出严正抗议
破索赔记录!东风日产诉自媒体侵权获胜:牛车实验室被判赔偿500万
三门峡市城乡一体化示范区(高新区)农业产业园运营中心:加快推进好阳河生态廊道建设 助推乡村振兴
上半年业务毛利率提升 均胜电子已实现连续5个季度盈利
特朗普,P01135809,嫌犯大头照发布!
三旺通信:业绩说明会定于9月5日举行
机械键盘轴体新巅峰——CHERRY发布全新MX2A轴体
颍上县教育局拟推荐2023年阜阳市学科带头人骨干教师人员名单公示
比深坑酒店还要深?上海市区挖了个洞,世界最大直径!年底试运营!
定兴县:农技专家指导灾后蔬菜生产
“一圈三化”构建新型基层医保经办服务体系
兴县优化营商环境领导小组送策上门 助企纾难
2023年海北中小学开学时间表 具体几月几号开学
跟上引才潮流 打造人才高地
2023中级经济师《财政税收》三色笔记 重点一目了然!
毕节职业学校有哪些专业?
珠海突现“五折卖房”?地产商降价抢跑,超20城推新房团购
每周至少6列!“粤港澳大湾区-湛江港-海南自贸港”海铁联运班列常态化开行
SHEIN收购Forever 21母公司股权,“小单快反”方法论输出全球
斯特拉马乔尼:阿兹蒙有丰富国际经验,穆帅在热刺时就想要他
日本敲定核废水排海!韩国人抢盐抢到股市,相关股票飙涨,中国海关发“定心丸”:进口下降29%
怎么快速有效的瘦蝴蝶臂_瘦蝴蝶臂的方法图解
富士莱:钱怡减持公司股份7.5万股 减持计划完成
我中国少年|扬少年之帆,让梦想远航
季度便览 | 2023年第二季度全国重点旅游城市2360家星级饭店共创造营业收入266.55亿元
《星空》具体发售时间
《星空》全球解锁时间公布!豪华版北京时间9月1日早上8点解锁!
九号公司半年净赚2.2亿元 小米是最大销售者
前迪士尼设计师怒斥《白雪公主》真人电影:称其为耻辱
水稻、瓜果陆续成熟 金秋时节看广袤大地忙碌丰收景象
胶印怎么快速去除(年检贴的胶印怎么去除?)
2023年各银行突然限额了 交通银行手机银行转账限额
恭喜姚明!恭喜乔帅!周琦状态复苏,中国男篮信心满满有望出线
现在当兵真好,不过难度挺大,不是一般人可以的
充电15分钟续航450km,昊铂GT抢先领跑800V超充时代
【科普中国军事科技】让反舰导弹致盲的舰载电子战系统如何工作?
新大陆(000997.SZ):上半年净利增139.09%至5.65亿元 拟10派2.8元
第18次MACD金叉,渝开发买入胜率如何?看数据说
立航科技(603261):成都股份有限公司独立董事辞职
酒精燃烧是化学性质吗(酒精燃烧)
南京再添一处必打卡美食街!“南湖记忆”乐活街区开街啦
回到清朝当总统(关于回到清朝当总统的基本详情介绍)
某宇宙房企暴力裁员!
Counterpoint:印度已成世界第二大手机生产国,出货量累计20亿部
硅烷科技:上半年净利润同比增长37.25%
张湾区车城路街道多措并举防范电信网络诈骗
南极海冰融化严重危及帝企鹅幼鸟
三达奥克2023年上半年净利1777.18万 同比增加115.53%
山东启动年度第二次“双随机、一公开”集中抽查
《燃冬》:寒夜里抱团取暖,天亮后各奔前程
多家银行提供精准服务 建立绿色通道 优先满足灾后重建信贷需求
把握智能化机遇 巩固轻工业优势
蓝营女首长互挺 台东县嘉义市交流青年政策
“我们有一口吃的,坚决不能让他们饿着” 风雨中这样的守护温暖感人
公务员报考放宽年龄限制后,考生却倍感尴尬:怎么和想的不一样
禾多科技改名 公司公司董事会发生变动
湿气原来“最怕”它,秋天每天坚持吃,健脾祛湿,开胃爽口,真鲜
iPhone 15 Pro Max与14 Pro Max参数对比:升级巨大 价格更贵
【HP乙女】蛊惑人心 ④ 上学前
射频导纳料位开关采购应注意的几点事项
鹊刀门传奇演员表 主创揭秘《鹊刀门传奇》幕后 基本情况讲解
和林微纳:8月24日获融资买入160.72万元,占当日流入资金比例5.81%
三代之后不留短板 小米MIX Fold 3终成全能折叠屏旗舰
法国延长燃煤电厂豁免至2024年以支持电力供应
判决书曝九江银行个贷“硬伤”,互联网贷款余额降至75亿
图片|张艺兴的小手势
女排欧锦赛最新战报!朱婷新队友怒砍27分,哈克31分难救主
英特尔14代酷睿曝光:Z790主板马上到来
西北能源监管局主要负责同志出席西北电网2023年网源协调工作会议
男子沉迷于直播打赏,诈骗独居老人近千万元后挥霍一空
前IMF首席经济学家:美联储保留加息选择权是正确的做法
新华指数|枣企随行就市 红枣价格指数微幅上行
国台办:民进党当局对两岸旅游荒谬的管控限制令人匪夷所思
郭台铭:在等柯来电 希望下周三人见面谈
《孤注一掷》票房突破32亿:豆瓣评分跌至6.9
华为分布式存储全闪新品重磅发布:降低SSD单盘价格!
《甄嬛传》的一处情节“Bug” 隐藏着很多人不知道的冷知识
假如吃了核污染的食物 会怎么样?
帮我们跳过安卓App广告的李跳跳被杀死了!这合理吗?
第六届世界绿色发展投资贸易博览会将于9月初在南昌举办
肇俊哲:国安如今势头很猛,但不管强敌有多强我们都会全力争胜
寻甸县金源乡:扎实抓好“三农”工作 全面推动乡村振兴
乐橙S2D-5M室内摄像头,为家庭安全提供智慧守护
两岸同胞携手同行,乘着两岸经济融合发展的大船奋勇向前(两岸观察)
深圳能源:上半年净利润18.78亿元 同比增74.86%
A股三大指数午后跌幅均超过1%,沪指跌破3100点
山西焦煤:目前没有收到相关信息,如有公司将及时予以披露
竹子的寓意和象征女人(竹子的寓意)
星火认知大模型首搭星纪元ES,星途携手科大讯飞定义智能汽车新未来