我已经通过转换纸笔RPG的脚本工装各地的红宝石。
现在我有一个角色的统计数据保存在散,我想能够通过公共的方法来设置。 我得到了与工作:
class Character
attr_reader :str, :con, :dex, :wis, :int, :level, :mods, :stats
def initialize str, con, dex, wis, int, cha, level = 1
@stats = { :str => str, :con => con, :dex => dex, :wis => wis, :int => int, :cha => cha }
@mods = {}
@level = level
@stats.each_pair do |key, value|
@mods[key] = ((value / 2 ) -5).floor
end
end
def []=(index, value)
@stats[index] = value
end
end
这使我实例化新的字符,然后更新@stats
通过运行newChar.stats[:str] = 12
然而,我也似乎能够修改@mods
使用这种方法为好,这是不希望的。 newChar.mods[:str] = 15
将成功地改变@mods
散列,从我的理解不应该有可能与当前的设置方法。
在一个稍微不同的音符,我使用创建我的迭代器@mods
哈希似乎笨重,但我还没有找到更好的东西来完成任务。
你甚至没有打电话给你的[]=
您的实例方法。 这将做如下所示:
newChar[:str] = 123
代替
newChar.stats[:str] = 123
所以调用newChar.stats[:str] = 123
,你甚至都不需要你的方法定义。 其原因是, newChar.stats
以及newChar.mods
都将返回实际的哈希然后可以改变。
一个可能的解决方法是冻结@mods
变量,因此它不能改变任何更多:
def initialize str, con, dex, wis, int, cha, level = 1
# omitted ...
@stats.each_pair do |key, value|
@mods[key] = ((value / 2 ) -5).floor
end
@mods.freeze
end
这是一个很好的解决方案,如果你不希望能够改变@mods
一次。 试图设置的值将导致错误:
newChar.mods[:con] = 123
# RuntimeError: can't modify frozen Hash
你的类里面,你可以,但是,覆盖@mods
完全。
总之,满级是:
class Character
attr_reader :str, :con, :dex, :wis, :int, :level, :mods, :stats
def initialize str, con, dex, wis, int, cha, level = 1
@stats = { :str => str, :con => con, :dex => dex, :wis => wis, :int => int, :cha => cha }
@mods = {}
@level = level
@stats.each_pair do |key, value|
@mods[key] = ((value / 2 ) -5).floor
end
@mods.freeze
end
end
如果你需要一个散列一个公共的getter,但你不希望用户修改散列- 你的类的实例变量 - ,你可以用DUP做到这一点。
class MyClass
....
def my_hash
@my_hash.dup
end
end
凡与溶液freeze
,如上所述,将冻结哈希即使你的课上,.dup的解决方案将让你从你的类中从外部改变哈希但不是。