从类外部访问实例变量

99

如果一个实例变量属于一个类,我可以直接使用类实例来访问该实例变量(例如@hello)吗?

class Hello
  def method1
    @hello = "pavan"
  end
end

h = Hello.new
puts h.method1
3个回答

176

是的,你可以像这样使用instance_variable_get

class Hello
  def method1
    @hello = "pavan"
  end
end

h = Hello.new
p h.instance_variable_get(:@hello) #nil
p h.method1                        #"pavan" - initialization of @hello
p h.instance_variable_get(:@hello) #"pavan"

如果变量未定义(例如我的示例中的第一次调用instance_variable_get),则会获得nil

正如安德鲁在评论中提到的:

你不应该将这种方式作为访问实例变量的默认方式,因为它违反了封装。

更好的方法是定义一个访问器:

class Hello
  def method1
    @hello = "pavan"
  end
  attr_reader :hello  
end

h = Hello.new
p h.hello #nil
p h.method1                        #"pavan" - initialization of @hello
p h.hello #"pavan"

如果您想要使用其他的方法名称,你可以通过 alias :my_hello :hello 来给访问器取另外一个名字。
如果类没有在你的代码中定义,而是在一个 gem 中:您可以 修改类 并且 向类中插入新函数

6
你不应该将这种方式作为访问实例变量的默认方法,因为它会破坏封装性。 - Andrew Marshall
@knut我们能不能像这样做 h = Hello.newh.method1h.hello - nik7
3
你可以使用 attr_reader :hello 定义一个访问器。 - knut
难道不应该是 alias my_hello hello,而不是 alias :my_hello :hello 吗? - anon
@QPaysTaxes 我了解alias需要符号作为参数,所以我的版本是正确的,并且想要保持原样。但我测试了你的代码,它也可以工作 - 我很惊讶。文档也使用符号,例如http://ruby.about.com/od/rubyfeatures/a/aliasing.htm - knut
1
对我来说,这对于规格说明非常好,因为您不希望将某些内容公开。 - baash05

26

你也可以通过这样调用attr_readerattr_accessor来实现:

class Hello
  attr_reader :hello

  def initialize
    @hello = "pavan"
  end
end


class Hello
  attr_accessor :hello

  def initialize
    @hello = "pavan"
  end
end

调用 attr_reader 会为给定的变量创建一个 getter

h = Hello.new
p h.hello        #"pavan"

调用 attr_accessor 将为给定变量创建一个 getter 和一个 setter

h = Hello.new
p h.hello        #"pavan"
h.hello = "John"
p h.hello        #"John"

如您所知,应相应地使用attr_readerattr_accessor。仅在需要gettersetter时使用attr_accessor,而在仅需要getter时,请使用attr_reader


1

如果有人想要访问并设置这个变量,以下是他们可以做到的:

puts h.instance_variable_get(:@hello) # nil
h.instance_variable_set(:@hello, "StackOverflow") # <- set the value
puts h.instance_variable_get(:@hello) # StackOverflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接