加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

[cocos2dx]cocos2dx-lua中class语法

发布时间:2020-12-14 21:18:42 所属栏目:百科 来源:网络整理
导读:在lua中,可以通过元表来实现类、对象、继承等。与元表相关的方法有 setmetatable()、__index、getmetatable()、__newindex 。 关键: 实现Lua面向对象可以分解为 类的定义和类的实例化 两个问题。 类的定义主要是实现继承,即怎么让子类拥有父类的方法集 。

在lua中,可以通过元表来实现类、对象、继承等。与元表相关的方法有setmetatable()、__index、getmetatable()、__newindex

关键:实现Lua面向对象可以分解为类的定义和类的实例化两个问题。类的定义主要是实现继承,即怎么让子类拥有父类的方法集类的实例化需要解决实例如何共享类的方法集,但独享自己的成员变量实例
方案:子类在定义时复制所有基类的方法,在实例化时将该类作为metatable的__index赋值给实例。这就是cocos2dx里面的lua class的实现。

function clone(object)--clone函数
  local lookup_table = {}--新建table用于记录
  local function _copy(object)--_copy(object)函数用于实现复制
    if type(object) ~= "table" then 
      return object   ---如果内容不是table 直接返回object(例如如果是数字字符串直接返回该数字该字符串)
    elseif lookup_table[object] then
      return lookup_table[object]--这里是用于递归滴时候的,如果这个table已经复制过了,就直接返回
    end
    local new_table = {}
    lookup_table[object] = new_table--新建new_table记录需要复制的二级子表,并放到lookup_table[object]中.
    for key,value in pairs(object) do
      new_table[_copy(key)] = _copy(value)--遍历object和递归_copy(value)把每一个表中的数据都复制出来
    end
    return setmetatable(new_table,getmetatable(object))--每一次完成遍历后,就对指定table设置metatable键值
  end
  return _copy(object)--返回clone出来的object表指针/地址
end
--[[
clone  深度克隆一个值。
格式:value = clone(值)
用法示例:
-- 下面的代码,t2 是 t1 的引用,修改 t2 的属性时,t1 的内容也会发生变化
local t1 = {a = 1,b = 2}
local t2 = t1
t2.b = 3    -- t1 = {a = 1,b = 3} <-- t1.b 发生变化
 
-- clone() 返回 t1 的副本,修改 t2 不会影响 t1
local t1 = {a = 1,b = 2}
local t2 = clone(t1)
t2.b = 3    -- t1 = {a = 1,b = 2} <-- t1.b 不受影响
--]]

--Create an class.
function class(classname,super)--super为继承的类
    local superType = type(super)
    local cls

    --如果父类既不是函数也不是table则说明父类为空
    if superType ~= "function" and superType ~= "table" then
        superType = nil
        super = nil
    end

    --如果父类的类型是函数或者是C对象
    if superType == "function" or (super and super.__ctype == 1) then
        -- inherited from native C++ Object
        cls = {}

        --如果父类是表则复制成员并且设置这个类的继承信息
        --如果是函数类型则设置构造方法并且设置ctor函数
        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
            cls.ctor = function() end
        end

        --设置类型的名称
        cls.__cname = classname
        cls.__ctype = 1

        --定义该类型的创建实例的函数为基类的构造函数后复制到子类实例
        --并且调用子数的ctor方法
        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
        --如果是继承自普通的lua表,则设置一下原型,并且构造实例后也会调用ctor方法
        -- inherited from Lua Object
        if super then
            cls = {}
            setmetatable(cls,{__index = 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
通过该方法,我们可以很方便的定义一个class、继承一个class
--声明一个类:
MyClass = class("MyClass")  
function MyClass:ctor()  
    print("MyClass:ctor()")  
end  
--定义一个对象  
local myclass = MyClass:new()  

--继承一个类:
--继承一个函数
GameLayer = class("GameLayer",function()local layer = cc.Layer:create() return layer end)  
local gamelayer = GameLayer:new()

ctor=constructor(构造函数)
dtor=destructor(析构函数)

1.在子类构造函数ctor()中要调用父类构造函数ctor(),这用self.super:ctor(param),这句话反应出并不会像C++那样,在创建子类实例时,自动调用父类的构造函数。
2.使用class(classname,super)来子类继承父类只会继承父类的成员函数,而不会继承父类的成员变量。

若要子类既要继承父类的成员函数也要继承父类的成员变量,且在创建子类实例时,自动调用父类的构造函数。这用下面的class(classname,super)

function class(classname,super)    
    local cls = {}
    if super then
        cls = {}
        for k,v in pairs(super) do cls[k] = v end
        cls.super = super
    else
        cls = {ctor = function() end}
    end

    cls.__cname = classname
    cls.__index = cls

    function cls.new(...)
        local instance = setmetatable({},cls)
        local create
        create = function(c,...)
             if c.super then -- 递归向上调用create
                  create(c.super,...)
             end
             if c.ctor then
                  c.ctor(instance,...)
             end
        end
        --create(instance,...)--若替换成instance:ctor(...)则先调用自己的构造函数,若自己没有,则调用父类的构造函数
        instance:ctor(...)
        instance.class = cls
        return instance
    end
    return cls
end

local BaseClass = class("BaseClass",nil)
function BaseClass:ctor(param)
     print("baseclass ctor")
     self._param = param
     self._children = {}
end
function BaseClass:addChild(obj)
     table.insert(self._children,obj)
     for k,v in ipairs(self._children) do
        print(k,v)
     end
end

local DerivedClass = class("DerivedClass",BaseClass)
function DerivedClass:ctor(param)
     print("derivedclass ctor")
end

local instance = DerivedClass.new("param1")
instance:addChild("child1")
--打印输出
--baseclass ctor
--derivedclass ctor
--1 child1
极具有参考价值的文章: Lua 面向对象实现

扩展阅读:Lua的面向对象程序设计

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读