Lua该如何实现一个类,实现继承
Lua是一门解释型语言,C++,C#,Java等高级语言都属于编译型语言,编译型语言同解释型语言有着很大差别。(看官请自行百度)
Lua没有类和继承的概念,但是很多业务场景中,我们会需要自行实现类与继承的概念,以方便开发工作:Lua中table 是一个很强大的东西。
不多说无关紧要的:进入正题:
1 --@param string classname 类名 2 --@param [mixed super] 父类或者创建对象实例的函数 3 4 function class(classname, super) 5 local superType = type(super) 6 local cls 7 8 if superType ~= "function" and superType ~= "table" then 9 superType = nil 10 super = nil 11 end 12 13 if superType == "function" or (super and super.__ctype == 1) then 14 -- inherited from native C++ Object 15 cls = {} 16 17 if superType == "table" then 18 -- copy fields from super 19 for k,v in pairs(super) do cls[k] = v end 20 cls.__create = super.__create 21 cls.super = super 22 else 23 cls.__create = super 24 cls.ctor = function() end 25 end 26 27 cls.__cname = classname 28 cls.__ctype = 1 29 30 function cls.new(...) 31 local instance = cls.__create(...) 32 -- copy fields from class to native object 33 for k,v in pairs(cls) do instance[k] = v end 34 instance.class = cls 35 instance:ctor(...) 36 return instance 37 end 38 39 else 40 -- inherited from Lua Object 41 if super then 42 cls = {} 43 setmetatable(cls, {__index = super}) 44 cls.super = super 45 else 46 cls = {ctor = function() end} 47 end 48 49 cls.__cname = classname 50 cls.__ctype = 2 -- lua 51 cls.__index = cls 52 53 function cls.new(...) 54 local instance = setmetatable({}, cls) 55 instance.class = cls 56 instance:ctor(...) 57 return instance 58 end 59 end 60 61 return cls 62 end
如果对象是指定类或其子类的实例,返回 true,否则返回 false
简单实例:
local Animal = class("Animal") local Duck = class("Duck", Animal) print(iskindof(Duck.new(), "Animal")) -- 输出 true
-- 定义名为 Shape 的基础类 local Shape = class("Shape") -- ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行 function Shape:ctor(shapeName) self.shapeName = shapeName printf("Shape:ctor(%s)", self.shapeName) end -- 为 Shape 定义个名为 draw() 的方法 function Shape:draw() printf("draw %s", self.shapeName) end -- -- Circle 是 Shape 的继承类 local Circle = class("Circle", Shape) function Circle:ctor() -- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数 -- 类名.super 可以访问指定类的父类 Circle.super.ctor(self, "circle") self.radius = 100 end function Circle:setRadius(radius) self.radius = radius end -- 覆盖父类的同名方法 function Circle:draw() printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus) end -- local Rectangle = class("Rectangle", Shape) function Rectangle:ctor() Rectangle.super.ctor(self, "rectangle") end -- local circle = Circle.new() -- 输出: Shape:ctor(circle) circle:setRaidus(200) circle:draw() -- 输出: draw circle, radius = 200.00 local rectangle = Rectangle.new() -- 输出: Shape:ctor(rectangle) rectangle:draw()
以上创建class 概念的方法是cocos2d 中使用到的方式,也是推荐的方式,这个方式可以在Unity 中同样适用。
第二种更简单实用的方式:
在Unity 开发过程中我们很多时候会采用热更新的解决方案,当然在cocos 开发过程中也一样,作为解释型语言,lua脚本可以作为资源被打包,逻辑写在lua脚本中
Account={name='li',balance=100} function Account:withdraw(v) self.balance=self.balance-v end function Account:new(o) o =o or {} --如果用户没有提供table,则创建一个 setmetatable(o,self) --设置o的原表为Account self.__index=self--设置Account的索引为它自身 return o end acc = Account:new() acc:withdraw(0) print(acc.balance) print(acc.name) ---------------Lua模拟继承--------------------------- --子类继承父类 SpecialAccount =Account:new({limit=1000}) --子类重写父类的方法 function SpecialAccount:withdraw(v) print('SpecialAccount的方法') self.balance=self.balance-v end --实例化一个子类对象 vip=SpecialAccount:new() --调用从写的方法 vip:withdraw(100) print(vip.balance)