我正在阅读《Lua 编程,第 4 版》,目的是解决该书中的每个练习。第 21 章p 中的最后一个练习。 172 如下(重点是我的):
双重表示的一种变体是使用代理来实现对象(称为“跟踪表访问”的部分)。每个对象都由一个空的代理表表示。内部表将代理映射到携带对象状态的表。该内部表无法从外部访问,但方法使用它来将其
self
参数转换为它们操作的真实表。使用此方法实现Account
示例并讨论其优缺点。 我的解决方案如下:
Account = {}
local proxyToAccount = {}
function Account:new ()
local proxy = {}
proxyToAccount[proxy] = { balance = 0 }
setmetatable(proxy, self)
self.__index = self
return proxy
end
function Account:balance ()
return proxyToAccount[self].balance
end
function Account:withdraw (v)
proxyToAccount[self].balance = proxyToAccount[self].balance - v
end
function Account:deposit (v)
proxyToAccount[self].balance = proxyToAccount[self].balance + v
end
return Account
这与书本本身提供的示例(上面几页)几乎没有什么不同:
local balance = {}
Account = {}
function Account:withdraw (v)
balance[self] = balance[self] - v
end
function Account:deposit (v)
balance[self] = balance[self] + v
end
function Account:balance ()
return balance[self]
end
function Account:new (o)
o = o or {} -- create table if user does not provide one
setmetatable(o, self)
self.__index = self
balance[o] = 0 -- initial balance
return o
end
return Account
我想征求您的意见,我是否正确理解了练习以及我的解决方案是否正确。预先感谢您!
Tracking table accesses
中所述,您失败了,您没有生成“双重表示的变体”,您只是复制了相同的代码,但将
balance
重命名为proxyToAccount
,我觉得错过了练习的重点。您打算使用代理解决问题,因为它应该产生不同的结果,然后您可以比较这些结果。
这是使用代理表的示例。可能会有更好的方法来做到这一点,可能会回来并对其进行调整。
local Account = {}
Account.__index = Account
function Account:withdraw (v)
self.balance = self.balance - v
end
function Account:deposit (v)
self.balance = self.balance + v
end
function Account:new()
local protected = setmetatable({balance = 0}, Account)
local proxy = {
deposit = function(self, v)
protected:deposit(v)
end,
withdraw = function(self, v)
protected:withdraw(v)
end,
}
local meta = {
__index = protected,
__newindex = function (t,k,v)
print("this table is read-only")
end,
}
setmetatable(proxy, meta)
return proxy
end
然后您可以使用这两种实现进行这些调用:
account = Account:new()
account:deposit(100)
print(account.balance)
有什么区别,做了多少索引,内存占用是多少,哪个更安全等等...