attr_reader attr_accessor ruby

attr_reader - attr_accessor ruby



Diferencia entre @instance_variable y attr_accessor (5)

Debido a que attr_accessor define métodos, puede llamarlos desde fuera de la clase. Una @variable solo es accesible desde dentro de la clase.

Acabo de empezar a aprender ruby ​​y no veo la diferencia entre una @instace_variable y un atributo declarado utilizando attr_accessor .

¿Cuál es la diferencia entre las siguientes dos clases:

class MyClass @variable1 end

y

class MyClass attr_accessor :variable1 end

Busqué muchos tutoriales en línea y todo el mundo usa una notación diferente. ¿Tiene que ver algo con la versión ruby? También busqué algunos hilos viejos en StackOverflow

¿Qué es attr_accessor en ruby?
¿Cuál es la diferencia entre estas dos definiciones de inicialización de clase Ruby?

Pero todavía no puedo averiguar cuál es la mejor manera de usar.


En OOPS tenemos un concepto llamado encapsulación, lo que significa que la representación interna de un objeto generalmente está oculta de la vista fuera de la definición del objeto. Solo el objeto "en sí" puede alterar su propio estado interno. El mundo exterior no puede.

Cada objeto suele definirse por su estado y comportamiento , en ruby ​​las variables de instancia se denominan estado interno o estado del objeto y, de acuerdo con OOPS, ningún otro objeto debe acceder al estado y al hacerlo nos adherimos a la Encapsulación.

ej: class Foo def initialize(bar) @bar = bar end end

Anteriormente, hemos definido una clase Foo y en el método de inicialización hemos inicializado una variable de instancia (atributo) o (propiedad). cuando creamos un nuevo objeto ruby ​​usando el nuevo método, que a su vez llama internamente al método initialize, cuando se ejecuta el método, la variable de instancia @bar se declara e inicializa y se guardará como estado del objeto.

Cada variable de instancia tiene su propio estado interno y es única para el objeto en sí, cada método que definimos en la clase alterará el estado interno del objeto de acuerdo con la definición y el propósito del método. Aquí el método de inicialización hace lo mismo, como crear una nueva variable de instancia.

var object = Foo.new(1) #<Foo:0x00000001910cc0 @bar=1>

En el fondo, ruby ​​ha creado una variable de instancia (@bar = 1) y ha almacenado el valor como estado del objeto dentro del objeto ''objeto''. podemos verificarlo con el método ''instance_variables'' y esos métodos devuelven una matriz que contiene todas las variables de instancia del objeto de acuerdo con el estado actual del objeto.

object.instance_variables #[ [0]: @bar ]

Podemos ver la variable de instancia ''@bar'' arriba. que se crea cuando llamamos el método de inicialización en el objeto. esta variable ''@bar'' no debería estar visible (oculta) por defecto y, por lo tanto, no puede ser vista por otras personas desde fuera del objeto, excepto el objeto, desde adentro. Pero, un objeto puede alterar su propio estado interno y esto significa que puede mostrar o cambiar los valores si le damos una forma de hacerlo, estos dos pueden hacerse creando una nueva instancia de métodos en la clase.

cuando queremos ver la variable @bar llamándola, obtenemos un error, ya que por defecto no podemos ver el estado de un objeto.

show = object.bar #NoMethodError: undefined method `bar'' for #<Foo:0x00000001910cc0 @bar=1> #from (irb):24 #from /home/.rvm/rubies/ruby-2.0.0-p648/bin/irb:12:in `<main>''

Pero podemos acceder a las variables mediante dos métodos, estos dos se denominan métodos de establecimiento y obtención , que permiten que el objeto muestre o cambie su estado interno (variables de instancia / atributos / propiedades) respectivamente.

class Foo def bar @bar end def bar=(new_bar) @bar = new_bar end end

Hemos definido los métodos getter (bar) y setter (bar =), podemos nombrarlos de cualquier manera, pero la variable de instancia debe ser la misma que la variable de instancia a la que queremos mostrar o cambiar el valor. los setters y getters son una violación de los conceptos OOPS de una manera pero también son métodos muy poderosos.

cuando definimos los dos métodos volviendo a abrir la clase y definiéndolos, cuando llamamos al objeto con los métodos, podemos ver las variables de instancia (aquí @foo) y cambiar su valor también.

object.bar 1 object.bar=2 2 object.bar 2

Aquí hemos llamado el método bar (getter) que devuelve el valor de @bar y luego hemos llamado bar = method (setter) al que le proporcionamos un new_value como argumento y cambia el valor de la variable de instancia (@bar) y podemos Míralo de nuevo llamando al método de la barra.

En ruby ​​tenemos un método llamado attr_accessor , que combina los métodos set y get, lo definimos por encima de las definiciones de métodos dentro de la clase. Los métodos attr_ * son atajos para crear métodos (setter y getter)

class Foo attr_accessor :bar end

tenemos que proporcionar un símbolo (: bar) como argumento al método attr_accessor que crea internamente los métodos setter y getter con los nombres de los métodos como nombre de símbolo suministrado.

Si solo necesitamos un método de obtención, podemos llamar a attr_reader: bar Si necesitamos solo un método de establecimiento, podemos llamar a attr_writer: bar

attr_accessor crea los métodos attr_writer y attr_reader

podemos suministrar tantas variables de instancia como queramos a los métodos attr_ * separados por comas

class Foo attr_writer :bar attr_reader :bar attr_accessor :bar, :baz end


Las variables de instancia no son visibles fuera de la clase.

class MyClass def initialize @message = "Hello" end end msg = MyClass.new @message #==> nil # This @message belongs to the global object, not msg msg.message #==> NoMethodError: undefined method `message'' msg.@message #==> SyntaxError: syntax error, unexpected tIVAR

Ahora, siempre puedes hacer esto:

msg.instance_eval { @message }

Pero eso es torpe y engañoso. Buscar en la clase de otra persona puede ser educativo, pero el código de su cliente no debería hacerlo si desea obtener resultados confiables. Por otro lado, si desea que los clientes puedan ver esos valores, no haga que utilicen instance_eval ; en su lugar, define un método que haga el truco:

class MyClass def message return @message end end msg.message # ==> "Hello"

Debido a que muchas veces quieres hacer eso, Ruby proporciona un atajo para que sea más fácil. El siguiente código tiene exactamente el mismo resultado que el código anterior:

class MyClass attr_reader :message end

Eso no es un nuevo tipo de variable; Es solo una forma abreviada de definir el método. Puede mirar msg.methods y ver que ahora tiene un método de message .

Ahora, ¿qué sucede si quiere permitir que los forasteros no solo vean el valor de una variable de instancia, sino que también lo cambien? Para eso, debe definir un método diferente para la asignación, con a = en el nombre:

class MyClass def message=(new_value) @message = new_value end end msg.message = "Good-bye" msg.message # ==> "Good-bye"

Tenga en cuenta que los operadores de asignación son semi-mágicos aquí; A pesar de que hay un espacio entre msg.message y = , Ruby todavía sabe que debe llamar al método message= . Los operadores de combinación como += y así sucesivamente también activarán las llamadas al método.

Nuevamente, este es un diseño común, por lo que Ruby también le brinda un atajo:

class MyClass attr_writer :message end

Ahora, si usa attr_writer por sí mismo, obtiene un atributo que se puede modificar, pero no ver. Hay algunos casos de uso extraños en los que eso es lo que quiere, pero la mayoría de las veces, si va a dejar que los forasteros modifiquen la variable, también querrá que ellos puedan leerla. En lugar de tener que declarar tanto attr_reader como attr_writer , puede declarar ambos al mismo tiempo:

class MyClass attr_accessor :message end

Nuevamente, esto es solo un atajo para definir métodos que le permiten obtener la variable de instancia desde fuera de la clase.


Una variable de instancia no es visible fuera del objeto en el que se encuentra; pero cuando crea un attr_accessor , crea una variable de instancia y también lo hace visible (y editable) fuera del objeto.

Ejemplo con variable de instancia (no attr_accessor )

class MyClass def initialize @greeting = "hello" end end m = MyClass.new m.greeting #results in the following error: #NoMethodError: undefined method `greeting'' for #<MyClass:0x007f9e5109c058 @greeting="hello">

Ejemplo usando attr_accessor :

class MyClass attr_accessor :greeting def initialize @greeting = "hello" end end m2 = MyClass.new m2.greeting = "bonjour" # <-- set the @greeting variable from outside the object m2.greeting #=> "bonjour" <-- didn''t blow up as attr_accessor makes the variable accessible from outside the object

Espero que eso quede claro.


attr_accesor le proporciona métodos para leer y escribir las variables de instancia. Las variables de instancia están diseñadas para ocultarse del mundo exterior y, por lo tanto, para comunicarnos con ellas, deberíamos tener métodos de acceso attr _ibute.