用于哈希属性的Ruby-Setter方法



我一直在使用Ruby,将纸笔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

这允许我实例化一个新字符,然后通过运行newChar.stats[:str] = 12 更新@stats

然而,我似乎也可以使用这种方法修改@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

如上所述,如果带有freeze的解决方案将冻结哈希,即使对于您的类也是如此,那么.dip解决方案将允许您从类内部而不是从外部修改哈希。

最新更新