Lua-面向对象中类的构造

Posted zzya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua-面向对象中类的构造相关的知识,希望对你有一定的参考价值。

在Lua中,我们可以通过table+function来模拟实现类。

 

而要模拟出类,元表(metatable)和__index元方法是必不可少的。

为一个表设置元表的方法:

table = {}

metatable = {}

setmetatable(table, metatable) 

或者

table = setmetatable({},{})

 

下面看一个简单的例子:

local t = {
    k1 = "aaa"
}
local mt = {
    k2 = "bbb",
    __index = {
        k3 = "ccc"
    }
}
setmetatable(t, mt)

print("k1:", t.k1, "k2:", t.k2, "k3:", t.k3)

输出:

k1:    aaa    k2:    nil    k3:    ccc

 

从例子可以看出,查找表元素时会从表的元表的__index键中查找。

查找一个表元素的规则如下:

1.在表中查找,如果找到,返回该元素;如果找不到,继续2
2.判断该表是否有元表,如果没有,返回nil;如果有,继续3
3.判断元表中是否有__index方法,
如果__index方法为nil,返回nil;
如果__index方法是一个表,则重复 1,2,3;
如果__index方法是一个函数,则返回该函数的返回值。 

 

除了有__index元方法外,还有__newindex,__add,__sub等很多原方法,可查看Lua文档

2.4 – Metatables and Metamethods

 

在了解了元表和元方法后,我们就可以模拟类的实现了。

local A = {
    a1 = "this is a1",
    a2 = 100
}

function A.new()
    local o = {}
    setmetatable(o, A)
    A.__index = A

    return o
end

function A:Print()
    print("This is A:Print ")
end

local a = A.new()
a:Print()

输出结果:

This is A:Print 

 

以上就是一个类的简单实现方式,当然,我们也可以把它的实现封装到一个function中,这样会更方便我们类的创建和使用。

 

下面是cocos2d引擎中,lua类的实现,以供参考:

 

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_

function class(classname, ...)
    local cls = {__cname = classname}

    local supers = {...}
    for _, super in ipairs(supers) do
        local superType = type(super)
        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
    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)
        instance.class = cls
        instance:ctor(...)
        return instance
    end
    cls.create = function(_, ...)
        return cls.new(...)
    end

    return cls
end
View Code

 

 

以上是关于Lua-面向对象中类的构造的主要内容,如果未能解决你的问题,请参考以下文章

面向对象中类的成员

python之面向对象

面向对象的编程思想和Java中类的概念与设计

C++ 中类的构造函数理解

PHP面向对象的特点

java中类的构造方法和普通的方法在使用上有啥区别?