Ruby变量范围

时间:2012-09-27 20:31:45

标签: ruby

# 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 个答案:

答案 0 :(得分:3)

当你说

var = value

始终是指局部变量var,即使您已定义方法varvar=也是如此。 (在您的情况下,您使用short_name定义的方法attr_reader,但您没有定义short_name=。)

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

@var = value

或者您可以将var=方法与明确的self接收方一起使用:

self.var = value

第二种形式仅适用于您明确定义var=方法或attr_accessorattr_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语句。