Lua本身是不能像C++那樣直接實現繼承,但我們可以用萬能的table表來實現。
以下我總結了三種方式的類以及繼承的實現
第一、官方的做法,使用元表實現 原理參照《Programming in lua》
Object.lua
Object = {class_id = 0} function Object:new(o) o = o or {} setmetatable(o,self) -- 對象o調用不存在的成員時都會去self中查找,而這里的self指的就是Object self.__index = self return o end
---以下我們創建對象來測試以下
local o1 = Object:new()
o1.class_id = 11;
local o2 = Object:new()
o2.class_id = 22;
以上我們就利用元表實現了一個類,但這個類沒有任何行為,以下我們繼承上面的類
DisplayObject.lua
DisplayObject = Object:new() -- 現在為止,DisplayObject只是Object的一個實例,注意以下代碼 D = DisplayObject:new(width = 100,height = 50) -- DisplayObject從Object繼承了new方法,當new執行的時候,self參數指向DisplayObject。所以,D的metatable是DisplayObject,__index 也是DisplayObject。這樣,D繼承了DisplayObject,后者繼承了Object。 ---在Lua中面向對象有趣的一個方面是你不需要創建一個新類去指定一個新的行為。
第二、復制表方式
我們同樣使用上面的Object,換種寫法
--Lua中的面向對象 --[[ 復制表方式面向對象 參數為一張表,通過遍歷這張表取值,賦給一張空表,最后返回新建的表,來達到克隆表 ]] function cloneTab(tab) local ins = {} for key, var in pairs(tab) do ins[key] = var end return ins end
Object = {class_id = 1}
function Object.new()
local o = cloneTab(Object)
return o
end
-- 使用這個類
local p = Object.new()
繼承實現
DisplayObject.lua
--[[ 復制表 第一參數是目標表,第二個參數是需要復制的表 通過遍歷tab來取值將它賦值到目標表中 ]] function copy(dist,tab) for key, var in pairs(tab) do dist[key] = var end end DisplayObject = {} function DisplayObject.new() local ss = Object.new() copy(ss,DisplayObject) return ss end
local p1 = DisplayObject.new()
第三,使用函數閉包的形式實現面向對象
--以函數閉包的形式實現面向對象 --定義一個方法,函數閉包實現一個類的概念 function People(name) local self = {} --初始化方法,私有的 local function init() self.name = name end self.sayHi = function () print("Hello "..self.name) end --調用初始化 init() return self end --實例化一個對象 local p = People("ZhangSan") p:sayHi() --函數閉包的形式實現類繼承 function Man(name) local self = People(name) -- local function init() -- -- end self.sayHello = function () print("Hi "..self.name) end return self end local m = Man("Lisi") --m:sayHello() m:sayHi()
PS;關於繼承類,cocos2d-x v3版本提供一個更好更便捷的方式來實現。使用class全局方法創建
如
require "Object" GameObject = class("GameObject",function () return Object:new() end) function GameObject:create() return GameObject.new() end
-- 以上就實現了一個繼承過程
在cocos引擎源代碼下有extern.lua這個文件,里面就聲明了class這個方法
extern.lua
function clone(object) local lookup_table = {} local function _copy(object) if type(object) ~= "table" then return object elseif lookup_table[object] then return lookup_table[object] end local new_table = {} lookup_table[object] = new_table for key, value in pairs(object) do new_table[_copy(key)] = _copy(value) end return setmetatable(new_table, getmetatable(object)) end return _copy(object) end --Create an class. function class(classname, super) local superType = type(super) local cls if superType ~= "function" and superType ~= "table" then superType = nil super = nil end if superType == "function" or (super and super.__ctype == 1) then -- inherited from native C++ Object cls = {} if superType == "table" then -- copy fields from super for k,v in pairs(super) do cls[k] = v end cls.__create = super.__create cls.super = super else cls.__create = super end cls.ctor = function() end cls.__cname = classname cls.__ctype = 1 function cls.new(...) local instance = cls.__create(...) -- copy fields from class to native object for k,v in pairs(cls) do instance[k] = v end instance.class = cls instance:ctor(...) return instance end else -- inherited from Lua Object if super then cls = clone(super) cls.super = super else cls = {ctor = function() end} end cls.__cname = classname cls.__ctype = 2 -- lua cls.__index = cls function cls.new(...) local instance = setmetatable({}, cls) instance.class = cls instance:ctor(...) return instance end end return cls end function schedule(node, callback, delay) local delay = cc.DelayTime:create(delay) local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback)) local action = cc.RepeatForever:create(sequence) node:runAction(action) return action end function performWithDelay(node, callback, delay) local delay = cc.DelayTime:create(delay) local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback)) node:runAction(sequence) return sequence end