Ruby – 哈希属性的Setter方法
通过将笔和纸RPG转换为脚本,我一直在使用Ruby。
现在我有一个角色的统计数据保存在哈希中,我希望能够通过公共方法设置。 我得到了这个:
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
这允许我实例化一个新角色,然后通过运行newChar.stats[:str] = 12
更新newChar.stats[:str] = 12
但是,我似乎也能够使用这种方法修改@mods
,这是不可取的。 newChar.mods[:str] = 15
将成功改变@mods
哈希值,根据我的理解,使用当前的setter方法是不可能的。
在一个稍微单独的注释中,我用来创建我的@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
如上所述,冻结解决方案即使对于您的类也会冻结哈希,.dup-solution将允许您从类中修改哈希,而不是从外部修改哈希。