lua--面向对象使用middleclass

昨天本来还想写一篇love2d之角色移动的,可是不知怎么回事,

我在一个类里有setXY(),在love.load()里调用了,可是居然没

按我的预想坐标,而是直接显示在了顶点.后来各种print,发现

确实是调用了,但就是不显示,郁闷,只好作罢.

后来也想不出原因,于是又看了一下lua面向对象,想到以后可能

很多地方会用到类,便想找一个简洁的lua面向对象的扩展.先推荐一个很好的lua博客,当lua语法不懂时,我常去翻阅.

到http://lua-users.org翻了一下,发现了一些面向对象的扩展,最终选择

了middleclass.middle意为中等,表明其是中等规模的

面向对象实现(作者介绍的),官网为https://github.com/kikito/middleclass/

不到140行代码就实现了,类,继承,虚函数,私有变量等.(下面的示例已带middleclass,可以不用下载)

作者也提到了没有实现的有

  • metaclasses   元类吗?不知道
  • classes are not Objects (instances are) 类的实例是Objects,而类不是
  • simulating a ‘super’ keyword (for performance concerns) 因为效率,没有模拟'super'关键字

根据作者的提示,简单的看看middleclass源码,发现在下面摘录的片断里第4步才setmetatable(),即在class的实例new()之后,

才把其绑定到Object上.(只是简单的看了一下,不确定正否,希望漂过的高手指正)

--1步
function
class(name, super, ...) super = super or Object return super:subclass(name, ...) end
--2
function Object.static:subclass(name)
  assert(_classes[self], "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
  assert(type(name) == "string", "You must provide a name(string) for your class")

  local subclass = _createClass(name, self)
  _setClassMetamethods(subclass)
  _setDefaultInitializeMethod(subclass, self)
  self.subclasses[subclass] = true
  self:subclassed(subclass)

  return subclass
end
--3
function Object.static:new(...)
  local instance = self:allocate()
  instance:initialize(...)
  return instance
end
--4
function Object.static:allocate()
  assert(_classes[self], "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
  return setmetatable({ class = self }, self.__instanceDict)
end

下面我们来使用middleclass,看其带来的方便之处(以下的内容来自官方文档,

英语好的同学可以自己去看).只介绍类和继承,其它的功能现在还用不上,等以后

再说.

test.lua

require 'middleclass'
--声明一个类,也可用class('Person', Object) 或Object:subclass('Person') middleclass的根类是Object
Person = class('Person')

--构造函数
function Person:initialize(name)
    self.name = name
end
function Person:speak()
    print('Hi, I am ' .. self.name ..'.')
end

--继承或Person:subclass('AgedPerson')
AgedPerson = class('AgedPerson', Person)
--类变量
AgedPerson.static.ADULT_AGE = 18

--注意在子类里要调用父类里的构造函数
function AgedPerson:initialize(name, age)
    Person.initialize(self, name) --注意在子类里要调用父类里的构造函数
    self.age = age
end

--覆盖子类里的方法,感觉确实像从c++里的虚函数
function AgedPerson:speak()
    Person.speak(self)
    --可以实例里直接访问类变量
    if(self.age < AgedPerson.ADULT_AGE) then
        print('I am a child.')
        else
        print('I am an adult.')
    end
end

--等价于AgedPerson('Billy the Kid', 13),new()隐含调用
local p1 = AgedPerson:new('Billy', 13)
local p2 = AgedPerson:new('Luke', 21)

p1:speak()
print("----------------")
p2:speak()

代码,已clone的直接git pull
git clone git://gitcafe.com/dwdcth/love2d-tutor.git
或git clone https://github.com/dwdcth/mylove2d-tutor-in-chinese.git

posted @ 2012-12-27 12:06  半山th  阅读(3021)  评论(1编辑  收藏  举报