现在我在Lua中使用closures for implementing OOP。下面是一个简略的例子。尝试在stronger_heal
内实施infested_mariner
时,我的问题就出现了。
--------------------
-- 'mariner module':
--------------------
mariner = {}
-- Global private variables:
local idcounter = 0
local defaultmaxhp = 200
local defaultshield = 10
function mariner.new ()
local self = {}
-- Private variables:
local hp = maxhp
-- Public methods:
function self.sethp (newhp)
hp = math.min (maxhp, newhp)
end
function self.gethp ()
return hp
end
function self.setarmorclass (value)
armorclass = value
updatearmor ()
end
return self
end
-----------------------------
-- 'infested_mariner' module:
-----------------------------
-- Polymorphism sample
infested_mariner = {}
function infested_mariner.bless (self)
-- New methods:
function self.strongerheal (value)
-- how to access hp here?
hp = hp + value*2
end
return self
end
function infested_mariner.new ()
return infested_mariner.bless (mariner.new ())
end
如果我将infested_mariner
定义放在另一个.lua文件中,它将无法访问全局私有变量,也无法访问基本.lua文件中定义的私有变量。如何让只有infested_mariner
可以访问的受保护成员,并且该解决方案不涉及将所有派生类与父项放在同一文件中?
注意:我目前正在子类中使用getter和setter。
答案 0 :(得分:1)
在Lua中,您只能访问其范围内的局部变量。为了让其他函数能够看到你的变量,你需要重写它,以便受保护的变量位于子类可以访问的表中。
实现此目的的一种方法是在当前类中创建公共属性,并使用命名约定(如以下划线开头的名称)来表示受保护的东西。您可能知道这一点,但我不得不说,我认为这种方法通常比实际受保护的变量更容易实现
。如果您想要真正的受保护变量,则需要将表格与公共内容和受保护的内容分开。一种方法是更改bless函数,以便它接收这两个表:
function infested_mariner.bless (pub, pro)
-- New methods:
function pub.strongerheal (value)
pro.hp = pro.hp + value*2
end
return pub
end
如何设置以便构造函数将受保护的表传递给彼此留下了一个练习。如果你走这条路线,你可能想要为你做一些功能,这样你就不会有机会每天触摸受保护的桌子。
答案 1 :(得分:1)
这是封闭方法的限制。无法从闭包之外访问hp
。
这是一种意识形态问题......有些人说保护成员制动封装,所以应该避免:将所有数据设为私有并在需要时扩展接口(添加公共功能)。那些说喜欢封闭式方法的人。
如果你想使用受保护的成员,我可能不使用闭包方法。一个好的命名约定可能是最容易的事情。
self.public_thing = "asdf"
self._protected_thing = "asdf"
当然,数据实际上是公开的,但这种方法效果很好。这几乎就是Python所做的。当你想弄乱内部时,它会派上用场,比如测试。