欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在 Lua 中实现类似于 Swift Extension 的机制

程序员文章站 2022-03-14 11:01:07
...

本文目标

本文在 Lua 中实现类似于 Swift Extension 的机制,使得在不改变类继承关系、不进行重复代码实现的前提下,实现一些函数的复用。主要作用是减少代码重复。主要思路是在运行时将作为 extensionClass 的表的元素依次拷贝到目标类中。

软件版本

  • Lua 5.1.5

代码

遍历扩展类/表,将其中的对象依次拷贝到目标类中。具体实现如下:

function extendClass(extensionDestinationClass, extensionSourceClass)
    for k, v in pairs(extensionSourceClass) do
        if extensionDestinationClass[k] ~= nil then
            print("key "..k.." overriden by extension class")
        end
        extensionDestinationClass[k] = v
    end
end

说明

该实现对 number 是按值拷贝,对 string(按 Lua 实现机制,本身就是存储的引用), function, table 是按引用拷贝。

相对于 Swift 的 extension 语法,因为此处 extension 类在定义时不需要指明是对哪个类的扩展,所以一次定义后可用于多种不同的类。而 Swift 则一个 extension 定义对应一个特定的实现,在这一点上本实现略有优势。

使用示例

testClass = {}

extensionClass = {}
function extensionClass:ExtendedPrint()
    print("hello a extended print")
end

extensionClass.testValue = 20


-- 由于搜索的复杂性,多重继承的效率比起单继承
-- 要低。一个简单的改善性能的方法是将继承方法拷贝到子类。

baseClass = {}
function baseClass:BasePrint()
    print("hello this is base print")
end


setmetatable(testClass, {__index = baseClass})
testClass:BasePrint()
--testClass:ExtendedPrint()

--setmetatable(testClass, {__index = extensionClass})


extendClass(testClass, extensionClass)
testClass:BasePrint()
testClass:ExtendedPrint()
print(extensionClass)
print(testClass)
extendClass(testClass, extensionClass)
testClass.testValue = 50

testClass2 = {}
extendClass(testClass2, extensionClass)
print(testClass.testValue)
print(testClass2.testValue)

配合 debugPrint模块 可以得到以下输出:

@test.lua(38,1) hello this is base print 
@test.lua(38,1) hello this is base print 
@test.lua(27,1) hello a extended print 
@test.lua(52,1) 
{
  testValue = 20,
  ExtendedPrint = "function: 01044A18"
} 
@test.lua(53,1) 
{
  ExtendedPrint = "function: 01044A18",
  testValue = 20
} 
@test.lua(10,1) key testValue overriden by extension class 
@test.lua(10,1) key ExtendedPrint overriden by extension class 
@test.lua(59,1) 50 
@test.lua(60,1) 20 

可见,testClass 与 testClass2 分别拥有不同的 testValue 实例。但是共用 ExtendedPrint 这个 function 的引用。

示例工程

参考资料

相关标签: Lua