Greifen Sie von außerhalb der Klasse auf die Instanzvariable zu

82

Wenn eine Instanzvariable zu einer Klasse gehört, kann ich dann @hellodirekt über die Klasseninstanz auf die Instanzvariable (z. B. ) zugreifen ?

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

h = Hello.new
puts h.method1
Pawan
quelle

Antworten:

148

Ja, Sie können Folgendes verwenden 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"

Wenn die Variable undefiniert ist (erster Aufruf von instance_variable_getin meinem Beispiel), erhalten Sie nil.


Wie Andrew in seinem Kommentar erwähnt:

Sie sollten dies nicht als Standard für den Zugriff auf Instanzvariablen festlegen, da dies die Kapselung verletzt.

Ein besserer Weg ist, einen Accessor zu definieren:

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"

Wenn Sie einen anderen Methodennamen möchten, können Sie den Accessor als Alias ​​verwenden : alias :my_hello :hello.

Und wenn die Klasse nicht in Ihrem Code, sondern in einem Juwel definiert ist: Sie können Klassen in Ihrem Code ändern und neue Funktionen in Klassen einfügen .

knut
quelle
6
Sie sollten dies nicht als Standard für den Zugriff auf Instanzvariablen festlegen, da dies die Kapselung verletzt.
Andrew Marshall
@knut können wir das nicht einfach so h = Hello.newund h.method1und machen h.hello?
Nik7
3
@nlingutla Sie können einen Accessor mitattr_reader :hello
knut
Wäre es alias my_hello hellonicht so alias :my_hello :hello?
Fund Monica Klage
1
Für mich ist dies ideal für Spezifikationen, bei denen Sie nichts öffentlich machen möchten.
Baash05
20

Sie können dies auch erreichen, indem Sie anrufen attr_readeroder attr_accessorwie folgt:

class Hello
  attr_reader :hello

  def initialize
    @hello = "pavan"
  end
end

oder

class Hello
  attr_accessor :hello

  def initialize
    @hello = "pavan"
  end
end

Durch Aufrufen attr_readerwird ein getterfür die angegebene Variable erstellt:

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

Durch Aufrufen attr_accessorwird ein getterUND setterfür die angegebene Variable erstellt:

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

Wie Sie vielleicht verstehen, verwenden Sie attr_readerund attr_accessorentsprechend. Verwenden attr_accessorSie nur, wenn Sie ein getterUND benötigen, setterund verwenden attr_readerSie, wenn Sie nur ein UND benötigengetter

Kevinvhengst
quelle