Uzyskaj dostęp do zmiennej instancji spoza klasy

82

Jeśli zmienna instancji należy do klasy, czy mogę uzyskać dostęp do zmiennej instancji (np. @hello) Bezpośrednio za pomocą instancji klasy?

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

h = Hello.new
puts h.method1
Pawan
źródło

Odpowiedzi:

148

Tak, możesz użyć w instance_variable_getten sposób:

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"

Jeśli zmienna jest niezdefiniowana (pierwsze wywołanie instance_variable_getw moim przykładzie), otrzymasz nil.


Jak wspomina Andrew w swoim komentarzu:

Nie należy ustawiać tego jako domyślnego sposobu uzyskiwania dostępu do zmiennych instancji, ponieważ narusza to hermetyzację.

Lepszym sposobem jest zdefiniowanie akcesora:

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"

Jeśli chcesz inną nazwę metody, można aliasu akcesor: alias :my_hello :hello.

A jeśli klasa nie jest zdefiniowana w twoim kodzie, ale w klejnocie: możesz modyfikować klasy w swoim kodzie i wstawiać nowe funkcje do klas .

knut
źródło
6
Należy nie zrobić to domyślny sposób dostępu do zmiennych instancji, gdyż narusza enkapsulacji.
Andrew Marshall,
@knut, czy nie możemy po prostu zrobić tego jak h = Hello.newi h.method1i h.hello?
nik7
3
@nlingutla Możesz zdefiniować akcesor za pomocąattr_reader :hello
knut
Nie byłoby to alias my_hello helloprawda alias :my_hello :hello?
Sfinansuj pozew Moniki
1
Dla mnie jest to świetne rozwiązanie do specyfikacji, w których nie chcesz publikować czegoś.
baash05
20

Możesz to również zrobić dzwoniąc attr_readerlub w attr_accessorten sposób:

class Hello
  attr_reader :hello

  def initialize
    @hello = "pavan"
  end
end

lub

class Hello
  attr_accessor :hello

  def initialize
    @hello = "pavan"
  end
end

Wywołanie attr_readerstworzy getterdla danej zmiennej:

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

Wywołanie attr_accessorutworzy getterAND a setterdla danej zmiennej:

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

Jak możesz zrozumieć, użyj attr_readeri attr_accessorodpowiednio. Używaj tylko attr_accessorwtedy, gdy potrzebujesz getterAND a setteri używaj, attr_readergdy potrzebujesz tylkogetter

Kevinvhengst
źródło