2
# encoding: utf-8
class Person
  attr_reader :short_name
  def initialize(short_name)
    @short_name = short_name
  end

  def greeting_line
    short_name = short_name.downcase
    "Hello #{short_name}"
  end
end

person = Person.new("MS. LEE")

puts person.short_name  => "MS. LEE"
puts person.greeting_line => NoMethodError: undefined method `downcase' for nil:NilClass

异常发生在“short_name = short_name.downcase”,因为 (short_name = short_name) 使 short_name 变为 nil。

为什么右侧的“short_name”没有从实例方法“short_name”获取值?

4

4 回答 4

3

当你说

var = value

总是指局部变量var,即使你有方法varvar=定义了。(在你的情况下,你有short_name定义的方法attr_reader,但你没有short_name=定义。)

你有几种方法可以解决这个问题。您可以直接使用实例变量:

@var = value

或者您可以将该var=方法与显式self接收器一起使用:

self.var = value

仅当您var=明确定义了方法或使用attr_accessoror定义了方法时,第二种形式才有效attr_writer

现在,当你做类似的事情时

foo = foo

总是foo在左侧引入一个局部变量。当 rubyfoo​​ 在 的右侧看到时=,它解析为局部变量 foo,因为foo现在在范围内。所以这总是设置foo回它的默认值,nil.

于 2012-09-27T21:54:01.320 回答
1

在您的情况下,greeting_line范围 short_name 指向局部变量而不是实例方法short_name,为了使这个示例正常工作,您应该使用self.short_name(这将告诉 ruby​​ 使用实例方法)

def greeting_line
 short_name = self.short_name.downcase
 "Hello #{short_name}"
end
于 2012-09-27T21:53:39.743 回答
0

您只是在引用 short_name 时忘记了 @

@short_name

是一个实例变量

short_name

是绑定到 greeting_line 函数范围的局部变量

试试这个:

def greeting_line
  short_name = @short_name.downcase
  "Hello #{short_name}"
end
于 2012-09-27T20:40:18.213 回答
0

你应该使用:

  attr_accessor :short_name

而不是 attr_reader。

attr_reader 在您的类中生成以下方法:

def short_name
  @short_name
end

attr_accessor 也将产生方法:

def short_name=(val)
  @short_name = val
end

这将允许您自由设置 short_name,因为它是一个局部变量。

这是一篇很好的博文,演示了 ruby​​ 中的 attr_reader、attr_writer 和 attr_accessor 语句。

于 2012-09-27T20:41:19.547 回答