Lua中的封装

3.6k 词

Lua中没有privatetable中的key/value可以随意访问,利用metatable虽然可以施加一些限制,但是实际上有各种方法可以绕过这些限制。
下面介绍一种方法,实现真正的封装。

local LuaClass = require "LuaClass"
local TestClass = LuaClass("TestClass")
local PrivateDataMap = LuaClass:PrivateDataMap{
    "MemberA",
    "MemberB",
}

function TestClass:GetMemberA()
return PrivateDataMap:Get(self, "MemberA")
end

function TestClass:SetMemberA(Value)
local ExistValue = PrivateDataMap:Get(self, "MemberA")
if ExistValue ~= Value then – 比较差异
PrivateDataMap:Set(self, "MemberA", Value)
DispatchXXX – 触发事件
end
end

function TestClass:GetMemberB()
return PrivateDataMap:Get(self, "MemberB")
end

上面这段代码中,每个object对应两个成员MemberAMemberB,因为PrivateDataMap是局部变量,所以外部的代码无法直接访问,只能通过TestClass提供的接口访问这些成员。
PrivateDataMap的实现方法如下:

function LuaClass:PrivateDataMap(MemberNameList)
    local DataMap = {}
    function DataMap:Set(Owner, MemberName, Value)
        local Owner2ValueMap = DataMap[MemberName]
        if Owner2ValueMap then
            Owner2ValueMap[Owner] = Value
        end
    end
<span class="k">function</span> <span class="nf">DataMap</span><span class="p">:</span><span class="n">Get</span><span class="p">(</span><span class="n">Owner</span><span class="p">,</span> <span class="n">MemberName</span><span class="p">)</span>
    <span class="kd">local</span> <span class="n">Owner2ValueMap</span> <span class="o">=</span> <span class="n">DataMap</span><span class="p">[</span><span class="n">MemberName</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">Owner2ValueMap</span> <span class="ow">and</span> <span class="n">Owner2ValueMap</span><span class="p">[</span><span class="n">Owner</span><span class="p">]</span>
<span class="k">end</span>

<span class="kd">local</span> <span class="n">CommonFunction</span> <span class="o">=</span> <span class="nb">require</span> <span class="s2">&#34;CommonFunction&#34;</span>
<span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">MemberName</span> <span class="k">in</span> <span class="nb">pairs</span><span class="p">(</span><span class="n">MemberNameList</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">DataMap</span><span class="p">[</span><span class="n">MemberName</span><span class="p">]</span> <span class="o">=</span> <span class="n">CommonFunction</span><span class="p">:</span><span class="n">CreateWeakTable</span><span class="p">()</span>
<span class="k">end</span>
<span class="k">return</span> <span class="n">DataMap</span>

end

其中,objectmember的对应关系存储在weaktable中,不会影响object的释放。