tutorial - ruby::




Warum Rubys attr_accessor, attr_reader und attr_writer verwenden? (4)

Alle obigen Antworten sind korrekt; attr_reader und attr_writer sind bequemer zu schreiben als manuell die Methoden eingeben, für die sie attr_writer sind. Abgesehen davon bieten sie eine viel bessere Leistung als das Schreiben der Methodendefinition selbst. Weitere Informationen finden Sie in Folie 152 von diesem Vortrag ( PDF ) von Aaron Patterson.

Ruby bietet eine praktische und bequeme Möglichkeit, Instanzvariablen mithilfe von Schlüsseln wie

attr_accessor :var
attr_reader :var
attr_writer :var

Warum sollte ich attr_reader oder attr_writer wählen, wenn ich einfach attr_accessor verwenden attr_accessor ? Gibt es etwas wie Leistung (was ich bezweifle)? Ich denke, es gibt einen Grund, sonst hätten sie solche Schlüssel nicht gemacht.


Es ist wichtig zu verstehen, dass Accessoren den Zugriff auf Variablen, nicht aber deren Inhalt einschränken. In Ruby, wie in einigen anderen OO-Sprachen, ist jede Variable ein Zeiger auf eine Instanz. Wenn Sie zum Beispiel ein Attribut für einen Hash haben und es als "schreibgeschützt" festlegen, können Sie immer seinen Inhalt ändern, nicht jedoch den Inhalt des Zeigers. Schau dir das an:

irb(main):024:0> class A
irb(main):025:1> attr_reader :a
irb(main):026:1> def initialize
irb(main):027:2> @a = {a:1, b:2}
irb(main):028:2> end
irb(main):029:1> end
=> :initialize
irb(main):030:0> a = A.new
=> #<A:0x007ffc5a10fe88 @a={:a=>1, :b=>2}>
irb(main):031:0> a.a
=> {:a=>1, :b=>2}
irb(main):032:0> a.a.delete(:b)
=> 2
irb(main):033:0> a.a
=> {:a=>1}
irb(main):034:0> a.a = {}
NoMethodError: undefined method `a=' for #<A:0x007ffc5a10fe88 @a={:a=>1}>
        from (irb):34
        from /usr/local/bin/irb:11:in `<main>'

Wie Sie sehen können, löschen Sie ein Schlüssel / Wert-Paar aus dem Hash @a, indem Sie neue Schlüssel hinzufügen, Werte ändern, ececetera. Sie können jedoch nicht auf ein neues Objekt zeigen, da es sich um eine schreibgeschützte Instanzvariable handelt.


Sie können die verschiedenen Accessoren verwenden, um Ihre Absicht jemandem mitzuteilen, der Ihren Code liest, und es einfacher machen, Klassen zu schreiben, die korrekt funktionieren, egal wie ihre öffentliche API aufgerufen wird.

class Person
  attr_accessor :age
  ...
end

Hier kann ich sehen, dass ich das Alter sowohl lesen als auch schreiben kann.

class Person
  attr_reader :age
  ...
end

Hier kann ich sehen, dass ich nur das Alter lesen darf. Stellen Sie sich vor, dass es vom Konstruktor dieser Klasse gesetzt wird und danach konstant bleibt. Wenn es einen Mutator (Schreiber) für das Alter gäbe und die Klasse geschrieben wäre, wenn angenommen wird, dass sich das Alter, sobald es gesetzt ist, nicht ändert, könnte ein Fehler aus dem Code resultieren, der diesen Mutator aufruft.

Aber was passiert hinter den Kulissen?

Wenn du schreibst:

attr_writer :age

Das wird übersetzt in:

def age=(value)
  @age = value
end

Wenn du schreibst:

attr_reader :age

Das wird übersetzt in:

def age
  @age
end

Wenn du schreibst:

attr_accessor :age

Das wird übersetzt in:

def age=(value)
  @age = value
end

def age
  @age
end

Wissend dass, hier ist eine andere Art darüber nachzudenken: Wenn du nicht die adtr _... Helfer hättest und die Accessoren selbst schreiben müsstest, würdest du noch mehr Accessoren schreiben als deine Klasse benötigt? Zum Beispiel, wenn Alter nur gelesen werden müsste, würden Sie auch eine Methode schreiben, die es erlaubt, geschrieben zu werden?


Sie möchten nicht immer, dass Ihre Instanzvariablen von außerhalb der Klasse vollständig zugänglich sind. Es gibt viele Fälle, in denen das Zulassen des Lesezugriffs auf eine Instanzvariable sinnvoll ist, das Schreiben jedoch nicht möglich ist (z. B. ein Modell, das Daten von einer schreibgeschützten Quelle abruft). Es gibt Fälle, in denen Sie das Gegenteil wollen, aber ich kann mir keine vorstellen, die nicht von meinem Kopf erfunden sind.





ruby