关于Lua中面向对象设计的一些研究

Positron 于 2022-08-05 发布

研究了八百年了

万恶之源: Metatable

Lua中table可以设置一个__metatable,这个__metatable里面会装一些有用的东西,比如当访问table中不存在的键时,姐十七号会在table.__metatable.__index中寻找相应的键(如果__index存在的话),并返回这个键的值。

写一个类

Lua的table可以封装对象的属性,往table里面塞function可以作为对象的方法。因此Lua中的table就可以作为一个对象来看待,我们只需要整一个大批量生成对象的function就行了。

-- 第一种方法: 直接在table中写匿名函数
MyClassA = {
    new = function(self, o, my_value)
        -- 有关实例化的内容
        o = o or {}
        setmetatable(o, self)
        self.__index = self
        
        -- 有关对象的内容(在new里接收的参数的处理)
        self.my_value = my_value or 0
        return o
    end
}

-- 第二种方法: 在table外写函数
MyClassB = {}
function MyClassB:new(o, my_value)
    -- 有关实例化的内容
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    
    -- 有关对象的内容(在new里接收的参数的处理)
    self.my_value = my_value or 0
    return o
end

a = MyClassA:new(nil, 10)
b = MyClassB:new(nil, 20)

一些说明:

用metatable生成类的实例

用相似的方法,我们可以做出一个仿真的 继承。

MyClassA = {
    new = function(self, o, my_value)
        -- 有关实例化的内容
        o = o or {}
        setmetatable(o, self)
        self.__index = self
        
        -- 有关对象的内容(在new里接收的参数的处理)
        self.my_value = my_value or 0
        return o
    end
}

ChildClassA = MyClassA:new() -- 这时MyClassA已经成了ChildClassA的metatable的__index了

function ChildClassA:greet()
    print('Hello! I am ' .. self.my_value)
end

cca = ChildClassA:new(nil, 114)
cca:greet()

我们新写的这个greet函数在ChildClassA里,对MyClassA没有影响,而ChildClassA的new方法与MyClassA一样,也就是 继承。

End.