除了读取实例变量之外,attr_reader在ruby中还具有其他用途

时间:2018-12-02 21:49:38

标签: ruby

我有以下代码段:

class Modi
  include Comparable

  MEDAL_VALS = {"Gold" => 3, "Silver"=> 2, "Bronze" => 1}

  #commenting out attr_reader below breaks the code
  attr_reader :type

  def initialize(type)
    @type = type
  end

  def <=>(other)
    MEDAL_VALS[type] <=> MEDAL_VALS[other.type]
  end
end

我的理解是attr_reader是一个简单的工具,可以打印出实例变量以进行检查/开发。

当我注释掉attr_reader :type并保留def <=>(other)不变时,我得到:

modi.rb:15:in `<=>': undefined local variable or method `type' for # 
<Modi:0x005609e878be80 @type="Bronze", @weight=5> (NameError)
Did you mean?  @type
    from modi.rb:29:in `<'
    from modi.rb:29:in `<main>'`

def <=>(other)更改为MODAL_VALS[@type] < MEDAL_VALS[other.type](当attr_reader被注释掉时)会导致以下错误:

modi.rb:15:in `<=>': undefined method `type' for # 
<Modi:0x0055e62ce2feb0 @type="Silver", @weight=10> (NoMethodError)
    from modi.rb:29:in `<'
    from modi.rb:29:in `<main>'

在这种情况下为什么需要使用吸气剂attr_reader :type? (@type应该可以工作..甚至是self.type-第一次遇到在同一类的另一个方法中调用实例变量的问题)

请解释。

1 个答案:

答案 0 :(得分:3)

您可以使用attr_reader作为创建方法的快捷方式,该方法返回与符号名称相同的实例变量名称。

您至少有3个选择:

  • 使用attr_reader :type和您的@type = type分配
  • 创建自己的def type; @type; end方法
  • 修改代码以使用@typeinstance_variable_get

if MEDAL_VALS[@type] < MEDAL_VALS[other.instance_variable_get('@type')]

但是,

attr_reader(主要)不用于调试/检查。用于减少样板代码。

此外,@type对于当前实例确实有效。您需要在我的最后一个示例中以@type调用instance_variable_get才能从other获取ivar。

通过attr_reader :typedef type方法添加公共访问器方法可以使类的意图更加清晰(例如,该ivar可以访问)

参考文献: