1.类
再Lua中可以使用表和函数实现面向对象,将函数和相关的数据放置放置于同一个表中就形成了对象。例如:
Measure = {width = 0, height = 0} function Measure:setWifth(v) self.width = self.width + v
end function Measure:setHeight(v) self.height = self.height + v end function Measure:getMeasure() print(self.width * self.height) end function Measure:new(o) o = o or {} setmetatable(o, {__index = self}) return o end local a = Measure:new() a:setHeight(100) a:setWifth(5) a:getMeasure()
上面这段代码"setmetatable(o, {__index = self})"这句话值得注意,根据再元表一章的学习,我们知道,这里的setmetatable负责创建o表的原型,当o在自己的表内找不到相应的方法时,便会到__index所指定的Measure类型中去寻找。
2.继承
继承可以用元表实现,它提供在父类中查找存在的方法和变量机制。
继承分为单继承和多重继承。
单继承:
childMeasure = Measure:new() function childMeasure:setHeight(v) self.height = self.height + v * 2 end function childMeasure:setWidth(v) self.width = self.width + v * 2 end local area = childMeasure:new() area:setHeight(100) area:setWidth(5) area:getMeasure()
多重继承:
在多重继承中,我们自己利用'__index'元方法定义恰当的访问行为。
如下,定义__index:
local function search (k, plist) for i=1, #plist do --注意 ,教程里面使用的是table.getn(plist),是有问题的,因为plist是一个table数组,并不是一个table-table类型,所以使用table.getn会报错,改成求数组的长度就可以了 local v = plist[i][k] -- try 'i'-th superclass if v then return v end end end function createClass (...) local c = {} -- new class args = {...} setmetatable(c, {__index = function (self, k) return search(k, args) end}) c.__index = c function c:new (o) o = o or {} setmetatable(o, c) return o end return c end
使用方法:
Named = {} function Named:getname () return self.name end function Named:setname (n) self.name = n end NameMeasure = createClass(Measure, Named) mmm = NameMeasure:new{name = "fdfdsf"} print(mmm:getname()) mmm:setHeight(60) mmm:setWidth(5) mmm:getMeasure()
注意:多重继承是有顺序的,根据createClass参数的顺序,如果两个类中存在相同的方法或者数据,则优先使用第一个参数的方法和数据。这一点可以从下面的代码中看出:
local function search (k, plist) for i=1, #plist do --注意 ,教程里面使用的是table.getn(plist),是有问题的,因为plist是一个table数组,并不是一个table-table类型,所以使用table.getn会报错,改成求数组的长度就可以了 local v = plist[i][k] -- try 'i'-th superclass if v then return v end end end