Lua本身是不支持面向对象的,但是可以利用table和元表、元方法进行面向对象的模拟!
以下是Cocos2d-lua中面向对象的实现!
function class(classname, ...)
local cls = {__cname = classname}
local supers = {...}
for _, super in ipairs(supers) do
local superType = type(super)
-- 基类的类型只能是table或者function(若为nil,则无基类),其他类型是无效的
assert(superType == "nil" or superType == "table" or superType == "function",
string.format("class() - create class \"%s\" with invalid super class type \"%s\"",
classname, superType))
if superType == "function" then
assert(cls.__create == nil,
string.format("class() - create class \"%s\" with more than one creating function",
classname));
-- if super is function, set it to __create
cls.__create = super
elseif superType == "table" then
if super[".isclass"] then
-- super is native class
assert(cls.__create == nil,
string.format("class() - create class \"%s\" with more than one creating function or native class",
classname));
cls.__create = function() return super:create() end
else
-- super is pure lua class
cls.__supers = cls.__supers or {}
cls.__supers[#cls.__supers + 1] = super
if not cls.super then
-- set first super pure lua class as class.super
cls.super = super
end
end
else
error(string.format("class() - create class \"%s\" with invalid super type",
classname), 0)
end
end
cls.__index = cls -- cls作为元表的时候,索引为自身
if not cls.__supers or #cls.__supers == 1 then -- 没有或者只有一个基类
setmetatable(cls, {__index = cls.super})
else -- 有多个基类
setmetatable(cls, {__index = function(_, key)
local supers = cls.__supers
for i = 1, #supers do
local super = supers[i]
if super[key] then return super[key] end
end
end})
end
if not cls.ctor then
-- add default constructor
cls.ctor = function() end
end
cls.new = function(...)
local instance
if cls.__create then
instance = cls.__create(...)
else
instance = {}
end
setmetatableindex(instance, cls) -- setmetatableindex见附录
instance.class = cls
instance:ctor(...)
return instance
end
cls.create = function(_, ...)
return cls.new(...)
end
return cls
end
基类:BaseClass.lua
local BaseClass = class("BaseClass")
function BaseClass:ctor()
print("BaseClass:ctor")
end
function BaseClass:printFunc()
print("this is BaseClass`s printFunc")
end
function BaseClass:testFunc()
print("this is BaseClass`s testFunc")
end
return BaseClass
派生类:DerivativeClass.lua
local baseClass = require("BaseClass"):create()
local DerivativeClass = class("DerivativeClass", baseClass)
function DerivativeClass:ctor()
print("DerivativeClass:ctor")
end
function DerivativeClass:printFunc()
print("this is DerivativeClass`s printFunc")
end
return DerivativeClass
test:
local baseClass = require("BaseClass"):create() -- 调用基类的默认构造函数ctor
baseClass:printFunc() -- 调用基类的printFunc函数
local derivativeClass = require("DerivativeClass"):create() -- 依次调用基类和派生类的默认构造函数
derivativeClass:printFunc() -- 调用派生类的printFunc函数(重写基类的printFunc函数)
derivativeClass:testFunc() -- 调用基类的testFunc函数
--[[
BaseClass:ctor
this is BaseClass`s printFunc
BaseClass:ctor
DerivativeClass:ctor
this is DerivativeClass`s printFunc
this is BaseClass`s testFunc
]]
local setmetatableindex_
setmetatableindex_ = function(t, index)
if type(t) == "userdata" then
local peer = tolua.getpeer(t)
if not peer then
peer = {}
tolua.setpeer(t, peer)
end
setmetatableindex_(peer, index)
else
local mt = getmetatable(t)
if not mt then mt = {} end
if not mt.__index then
mt.__index = index
setmetatable(t, mt)
elseif mt.__index ~= index then
setmetatableindex_(mt, index)
end
end
end
setmetatableindex = setmetatableindex_
Just Mark!