attr_reader attr_accessor ruby

¿Por qué usar Ruby''s attr_accessor, attr_reader y attr_writer?



attr_accessor ruby (5)

Ruby tiene esta forma práctica y conveniente de compartir variables de instancia usando teclas como

attr_accessor :var attr_reader :var attr_writer :var

¿Por qué elegiría attr_reader o attr_writer si simplemente pudiera usar attr_accessor ? ¿Hay algo como el rendimiento (que dudo)? Supongo que hay una razón, de lo contrario no habrían hecho esas claves.


Es importante entender que los accesores restringen el acceso a la variable, pero no a su contenido. En ruby, como en otros idiomas OO, cada variable es un puntero a una instancia. Entonces, si tiene un atributo para un Hash, por ejemplo, y establece que sea "solo lectura", siempre podría cambiar su contenido, pero no el contenido del puntero. Mira esto:

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>''

Como puede ver, es posible eliminar un par clave / valor del Hash @a, como agregar nuevas claves, cambiar valores, etc. Pero no puede apuntar a un nuevo objeto porque es una variable de instancia de solo lectura.


No siempre desea que sus variables de instancia sean completamente accesibles desde fuera de la clase. Hay muchos casos en los que permitir el acceso de lectura a una variable de instancia tiene sentido, pero escribir en ella podría no serlo (por ejemplo, un modelo que recupera datos de una fuente de solo lectura). Hay casos en los que quieres lo contrario, pero no puedo pensar en ninguno que no haya sido creado de la mejor manera posible.


No todos los atributos de un objeto se deben establecer directamente desde fuera de la clase. Tener escritores para todas las variables de su instancia es generalmente un signo de encapsulación débil y una advertencia de que está introduciendo demasiado acoplamiento entre sus clases.

Como ejemplo práctico: escribí un programa de diseño donde colocas artículos dentro de contenedores. El elemento tenía attr_reader :container , pero no tenía sentido ofrecer un escritor, ya que la única vez que el contenedor del elemento debería cambiar es cuando se coloca en uno nuevo, lo que también requiere información de posicionamiento.


Puede usar los diferentes accesores para comunicar su intención a alguien que esté leyendo su código, y facilitar la escritura de clases que funcionarán correctamente sin importar cómo se llame a su API pública.

class Person attr_accessor :age ... end

Aquí, puedo ver que puedo leer y escribir la edad.

class Person attr_reader :age ... end

Aquí, puedo ver que sólo puedo leer la edad. Imagina que está establecido por el constructor de esta clase y después de eso permanece constante. Si hubiera un mutador (escritor) para la edad y la clase se escribiera asumiendo que esa edad, una vez establecida, no cambia, entonces podría producirse un error por el código que llama a ese mutador.

Pero, ¿qué está pasando detrás de las escenas?

Si tú escribes:

attr_writer :age

Eso se traduce en:

def age=(value) @age = value end

Si tú escribes:

attr_reader :age

Eso se traduce en:

def age @age end

Si tú escribes:

attr_accessor :age

Eso se traduce en:

def age=(value) @age = value end def age @age end

Sabiendo eso, aquí hay otra manera de pensarlo: si no tuviera los ayudantes attr _... y tuviera que escribir los accesores usted mismo, ¿escribiría más accesores de los que su clase necesitaba? Por ejemplo, si solo fuera necesario leer la edad, ¿escribiría también un método que permita escribirla?


Todas las respuestas anteriores son correctas; attr_reader y attr_writer son más convenientes para escribir que para escribir manualmente los métodos para los que son abreviados. Aparte de eso, ofrecen un rendimiento mucho mejor que escribir la definición del método. Para más información, vea la diapositiva 152 en adelante de esta charla ( PDF ) por Aaron Patterson.