红宝石 - setter方法散特性(Ruby - Setter methods for hash

2019-09-28 09:51发布

我已经通过转换纸笔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哈希似乎笨重,但我还没有找到更好的东西来完成任务。

Answer 1:

你甚至没有打电话给你的[]=您的实例方法。 这将做如下所示:

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


Answer 2:

如果你需要一个散列一个公共的getter,但你不希望用户修改散列- 你的类的实例变量 - ,你可以用DUP做到这一点。

class MyClass
  ....
  def my_hash
    @my_hash.dup
  end
end

凡与溶液freeze ,如上所述,将冻结哈希即使你的课上,.dup的解决方案将让你从你的类中从外部改变哈希但不是。



文章来源: Ruby - Setter methods for hash properties