【问题标题】:Setting with accessors in initialize results in nil properties在初始化中使用访问器设置会导致 nil 属性
【发布时间】:2016-05-18 05:32:22
【问题描述】:

为什么最后一行的结果是 nil 而不是 15

class TextC
  attr_accessor :thing1  
  def initialize
    thing1 = 15
    puts "thing: #{thing1}"
    some_method
  end  
  def some_method
    puts "ho there, wanderer"
  end
end  
tc = TextC.new
# thing: 15
# ho there, wanderer
# => #<TextC:0x007fe5617f1b30>
tc.thing1
# => nil

我们已经确定 Ruby 将 thing1=value 视为局部变量的设置,但为什么呢?

为什么访问器方法没有被推断为我正在尝试做的事情,但是 some_method 呢? attr_accessor 结果是否仅在初始化后计算?

【问题讨论】:

  • 它把它当作本地人。
  • 谁提议关闭这个问题?这很愚蠢。

标签: ruby


【解决方案1】:

attr_accessor :thing1 定义了一个访问实例变量@thing1 的属性。实例变量总是以@ 为前缀。

分配thing1 = 15 会在initialize 方法中创建一个局部变量。它不调用属性 writer,所以实例变量@thing1 的值没有设置。因为@thing1还没有被赋值,所以属性读取器tc.thing1会返回nil

赋值表达式,例如 thing1 = 15,没有显式接收器 (tc.thing1 = 15) 并且不是 Ruby 中的实例或类变量(@thing1 = 15@@thing1 = 15)将始终 定义和/或分配一个局部变量。要调用属性 writer(并让它设置实例变量),您需要显式指定接收者,例如self.thing1 = 15.

原因是因为在 Ruby 中你不会在分配变量之前声明它们。像 thing1 = 15 这样的表达式会产生歧义,因此 Ruby 选择让它始终引用局部变量。

在没有明确接收者的情况下调用不是属性编写器的方法(名称不以= 结尾的方法)没有问题,因为没有歧义。因此initialize 中的表达式some_method 将调用方法some_method

attr_accessor 定义的属性可立即使用。任何方法都会遇到相同的行为,而不仅仅是initialize

【讨论】:

  • 我想我过早地接受了这个答案,没有深入挖掘。我已经更新了我的问题。如果可以,请查看并随时编辑您的答案并进行更深入的解释。
  • 非常感谢您花时间解释这个关于什么选择赢得歧义竞赛的 Ruby 政策:]
【解决方案2】:

因为@thing1没有初始化,调用时默认返回nil

【讨论】:

  • 应该如何初始化?您的回答没有用,因此投反对票!
  • @vee 它准确地回答了为什么它返回nil。如果您想提出自己的问题,请打开一个新问题。
  • 虽然不是很完整的解释,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-03
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 2010-12-26
相关资源
最近更新 更多