# 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”获取值?
答案 0 :(得分:3)
当你说
时var = value
始终是指局部变量var
,即使您已定义方法var
和var=
也是如此。 (在您的情况下,您使用short_name
定义的方法attr_reader
,但您没有定义short_name=
。)
你有几种解决方法。您可以直接使用实例变量:
@var = value
或者您可以将var=
方法与明确的self
接收方一起使用:
self.var = value
第二种形式仅适用于您明确定义var=
方法或attr_accessor
或attr_writer
定义的方法。
现在,当您执行类似
的操作时foo = foo
此始终在左侧引入了一个局部变量foo
。当ruby看到foo
右侧的=
时,它会解析为本地变量 foo
,因为foo
现在在范围内。因此,这始终只是将foo
设置回其默认值nil
。
答案 1 :(得分:1)
在greeting_line
范围内的情况下,short_name指向局部变量而不是实例方法short_name
,为此示例工作,您应该使用self.short_name
(这将告诉ruby使用实例方法)
def greeting_line
short_name = self.short_name.downcase
"Hello #{short_name}"
end
答案 2 :(得分:0)
在引用short_name
时,您只是忘记了@@short_name
是一个实例变量
short_name
是绑定到greeting_line函数
范围的局部变量试试这个:
def greeting_line
short_name = @short_name.downcase
"Hello #{short_name}"
end
答案 3 :(得分: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,因为它是一个局部变量。
这是一个nice blog post,用于演示ruby中的attr_reader,attr_writer和attr_accessor语句。