Skip to content

Lua中类的实现

Lua的面向对象

Lua不直接支持面向对象编程,但是可以使用Lua中的表实现类似的功能。

lua
Vector = {
    x = 1,
    y = 2,
    z = 3,
}

function Vector:length()
    return math.sqrt((self.x * self.x) + (self.y * self.y) + (self.z * self.z));
end

print(Vector:length())

但是这不是我们想要的实现,我们想要的是,而不是对象。

简洁的class实现

我们可以使用Lua中的元表来帮我们实现对象模板,也就是类class概念。

lua
function class(baseClass, body)
    local ret = body or {}

    if (baseClass ~= nil) then
        setmetatable(ret, ret)
        ret.__index = baseClass
        ret.base = baseClass
    end

    -- 使用__index元方法创建对象
    ret.new = function (self, constructionData, originalSubClass)
        local obj
        if (self.__index ~= nil) then
            if (originalSubClass ~= nil) then
                obj = self.__index:new(constructionData, originalSubClass)
            else
                obj = self.__index:new(constructionData, self)
            end
        else
            obj = constructionData or {}
        end

        setmetatable(obj, obj)

        -- 设置读取对象属性/方法时的查找表,也就是类
        obj.__index = self

        -- 复制操作运算符
        if (self.__operators ~= nil) then
            for key, value in pairs(self.__operators) do
                obj[key] = value
            end
        end

        return obj
    end

    ret.isInstance = function (self, otherClass)
        local cls = self.__index
        while cls do
            if cls == otherClass then
                return true
            end
            -- 递归查找
            cls = cls.base
        end

        return false
    end

    return ret
end

使用方式

lua
------------------------------------------
require("LuaClass")

------------------------------------------

Vec3 = class(nil, {
    x = 0,
    y = 0,
    z = 0
})

function Vec3:length()
    return math.sqrt((self.x * self.x) + (self.y * self.y) + (self.z * self.z))
end

vec3 = Vec3:new({x = 1, y = 2, z = 3})
print(vec3:length())

------------------------------------------
Vec4 = class(Vec3, {
    w = 4
})

function Vec4:length()
    return math.sqrt((self.x * self.x) + (self.y * self.y) + (self.z * self.z) + (self.w * self.w))
end

vec4 = Vec4:new({x = 1, y = 2, z = 3, w = 4})
print(vec4:length())

------------------------------------------
print(vec4:isInstance(Vec3))

Github

https://github.com/TechArtLife/LuaClass

注意:可能有坑!!!

lua
require("LuaClass")
------------------------------------------
Vec3 = class(nil, {
    data = {1, 2, 3, x = 0}
})

function Vec3:SetData(value)
    self.data.x = value;
end

a = Vec3:new()
b = Vec3:new()

a:SetData(66)
b:SetData(100)
print("a.data.x is :" .. tostring(a.data.x));
print("b.data.x is :" .. tostring(b.data.x));
print("ClassBase.data.x is :" .. tostring(Vec3.data.x));

输出结果

shell
a.data.x is :100
b.data.x is :100
ClassBase.data.x is :100

参考资料

  1. A simple Class implementation in Lua for Object-Oriented Programming: https://gist.github.com/paulmoore/1429475
  2. Lua实现Class遇到的一个坑: https://zhuanlan.zhihu.com/p/95306318