这两天在看lua面向对象编程,在此记录一下自己看完后写的demo代码。
在Lua中,table就是一种对象,可以拥有状态与方法。如:
--[[ lua table实现OO]]-- base classfunction personCreate(name, age) local p = {name = name or 'unknow', age = age or 0} p.__index = p setmetatable(p, p) function p:setName(name) self.name = name end function p:getName() return self.name end function p:setAge(age) self.age = age end function p:getAge() return self.age end function p:toString(sep) local _sep = sep or ', ' return 'name:' .. self.name .. _sep .. 'age:' .. self.age end return pend-- inheritfunction studentCreate(name, age, score) local s = personCreate(name, age) -- create base class object s.score = score or 0 function s:setScore(score) self.score = score end function s:getScore() return self.score end function __toStringFactory(func) function toString(self, sep) local _sep = sep or ', ' return func(self, _sep) .. _sep .. 'score:' .. self.score end return toString end -- override toString function s.toString = __toStringFactory(s.toString) return send
测试代码如下:
local student = studentCreate('billy', 28, 70)print(student:toString())student:setScore(90)student:setName('Lily')print(student:toString('\t'))--[[输出结果:name:billy, age:28, score:70name:Lily age:28 score:90]]
但是上面的代码还有一个问题,即对象的状态缺少封装性,我们可以不调用setter/getter,直接修改属性。要解决这个,可以通过两个table来表示一个对象,一个table用来保存对象的状态,另一个用于保存对象的方法(接口)。为了避免未授权的访问,表示状态的table不保存在其他的table中,只是保存在方法的closure中。下面的代码重新对上述的类进行设计:
--[[ lua closure实现OO]]-- base classfunction personCreate(name, age) local self = {name = name or 'unknow', age = age or 0} -- upvalue local p = {} function p.setName(name) self.name = name end function p.getName() return self.name end function p.setAge(age) self.age = age end function p.getAge() return self.age end function p.toString(sep) local _sep = sep or ', ' return 'name: ' .. self.name .. _sep .. 'age: ' .. self.age end return pend-- inheritfunction studentCreate(name, age, score) local self = {score = score or 0} local s = personCreate(name ,age) function s.setScore(score) self.score = score end function s.getScore() return self.score end function __toStringFactory(func) function __toString(sep) local _sep = sep or ', ' return func(_sep) .. _sep .. 'scord: ' .. self.score end return __toString end -- override toString function s.toString = __toStringFactory(s.toString) return send
测试代码:
local student = studentCreate('billy', 28, 70)print(student.toString())student.setName('Lily')student.setScore(90)print(student.toString('\t'))--[[输出结果:name: billy, age: 28, scord: 70name: Lily age: 28 scord: 90]]