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.statsnewChar.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将允许您从类中修改哈希,而不是从外部修改哈希。