Доступ к переменной экземпляра извне класса

82

Если переменная экземпляра принадлежит классу, могу ли я получить доступ к переменной экземпляра (например @hello) напрямую, используя экземпляр класса?

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

h = Hello.new
puts h.method1
Pawan
источник

Ответы:

148

Да, можно использовать 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.

И если класс определен не в вашем коде, а в геме: вы можете изменять классы в своем коде и вставлять в классы новые функции .

кнут
источник
6
Вы не должны использовать этот способ доступа к переменным экземпляра по умолчанию, поскольку это нарушает инкапсуляцию.
Эндрю Маршалл
@knut мы не можем просто сделать это как h = Hello.newи h.method1и h.hello?
nik7
3
@nlingutla Вы можете определить аксессуар с помощьюattr_reader :hello
knut
Разве не было бы alias my_hello hello, не так alias :my_hello :helloли?
Иск Фонда Моники
1
По мне, это отлично подходит для спецификаций, когда вы не хотите обнародовать что-то.
baash05
20

Вы также можете сделать это, позвонив attr_readerили attr_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создаст getterAND setterдля данной переменной:

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

Как вы понимаете, используйте attr_readerи attr_accessorсоответственно. Используйте только attr_accessorтогда, когда вам нужно getterИ, setterи используйте, attr_readerкогда вам нужен толькоgetter

Кевинвенгст
источник