Qué es attr accessor en Ruby?
Estoy teniendo dificultades para entender attr_accessor
en Ruby. ¿Alguien puede explicarme esto?
18 answers
Digamos que tienes una clase Person
.
class Person
end
person = Person.new
person.name # => no method error
Obviamente nunca definimos el método name
. Hagámoslo.
class Person
def name
@name # simply returning an instance variable @name
end
end
person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error
Aha, podemos leer el nombre, pero eso no significa que podamos asignar el nombre. Esos son dos métodos diferentes. El primero se llama lector, y el segundo se llama escritor. Aún no creamos al escritor, así que hagámoslo.
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
Impresionante. Ahora podemos escribir y leer variable de instancia @name
usando los métodos reader y writer. Excepto, esto se hace con tanta frecuencia, ¿por qué perder el tiempo escribiendo estos métodos cada vez? Podemos hacerlo más fácil.
class Person
attr_reader :name
attr_writer :name
end
Incluso esto puede volverse repetitivo. Cuando usted quiere lector y escritor solo tiene que utilizar accessor!
class Person
attr_accessor :name
end
person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
Funciona de la misma manera! Y adivina qué: la variable de instancia @name
en nuestro objeto person se establecerá como cuando lo hicimos manualmente, por lo que puede usarlo en otros métodos.
class Person
attr_accessor :name
def greeting
"Hello #{@name}"
end
end
person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
Eso es todo. Para entender cómo attr_reader
, attr_writer
, y attr_accessor
métodos en realidad generar métodos para usted, leer otras respuestas, libros, ruby docs.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-10 21:28:46
Attr_accessor es solo un método. (El enlace debe proporcionar más información sobre cómo funciona - mire los pares de métodos generados, y un tutorial debe mostrarle cómo usarlo.)
El truco es que class
es no una definición en Ruby (es "solo una definición" en lenguajes como C++ y Java), sino que es una expresión que evalúa. Es durante esta evaluación cuando se invoca el método attr_accessor
que a su vez modifica la clase actual - recuerde el receptor implícito: self.attr_accessor
, donde self
es el objeto de clase "open" en este punto.
La necesidad de attr_accessor
y amigos, es, bueno:
Ruby, al igual que Smalltalk, no permite que se acceda a variables de instancia fuera de los métodos1 por ese objeto. Es decir, no se puede acceder a las variables de instancia en la forma
x.y
como es común en, por ejemplo, Java o incluso Python. En Rubyy
siempre se toma como un mensaje a enviar (o"método a llamar"). Así los métodosattr_*
crear envoltorios que proxy la instancia@variable
acceso a través de métodos creados dinámicamente.[14]} {[29]]}
Espero que esto aclare algunos de los pequeños detalles. Feliz codificación.
1 Esto no es estrictamente cierto y hay algunas "técnicas" alrededor de este , pero no hay soporte de sintaxis para el acceso de "variable de instancia pública".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:48
attr_accessor
es (como se indica @pst) solo un método. Lo que hace es crear más métodos para usted.
Así que este código aquí:
class Foo
attr_accessor :bar
end
Es equivalente a este código:
class Foo
def bar
@bar
end
def bar=( new_value )
@bar = new_value
end
end
Puedes escribir este tipo de método tú mismo en Ruby:
class Module
def var( method_name )
inst_variable_name = "@#{method_name}".to_sym
define_method method_name do
instance_variable_get inst_variable_name
end
define_method "#{method_name}=" do |new_value|
instance_variable_set inst_variable_name, new_value
end
end
end
class Foo
var :bar
end
f = Foo.new
p f.bar #=> nil
f.bar = 42
p f.bar #=> 42
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:29:34
attr_accessor
es muy simple:
attr_accessor :foo
Es un atajo para:
def foo=(val)
@foo = val
end
def foo
@foo
end
No es más que un getter/setter para un objeto
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:28:47
Básicamente falsifican atributos de datos de acceso público, que Ruby no tiene.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:11:11
Es solo un método que define los métodos getter y setter por ejemplo variables. Un ejemplo de aplicación sería:
def self.attr_accessor(*names)
names.each do |name|
define_method(name) {instance_variable_get("@#{name}")} # This is the getter
define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
end
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:29:29
También me enfrenté a este problema y escribí una respuesta algo larga a esta pregunta. Hay algunas grandes respuestas sobre esto ya, pero cualquiera que busque más aclaraciones, espero que mi respuesta pueda ayudar
Método de inicialización
Initialize le permite establecer datos en una instancia de un objeto al crear la instancia en lugar de tener que establecerlos en una línea separada en su código cada vez que crea una nueva instancia de la clase.
class Person
attr_accessor :name
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
person = Person.new("Denis")
puts person.greeting
En el código anterior estamos establecer el nombre "Denis" usando el método initialize pasando Dennis a través del parámetro en Initialize. Si queríamos establecer el nombre sin el método initialize, podríamos hacerlo así:
class Person
attr_accessor :name
# def initialize(name)
# @name = name
# end
def greeting
"Hello #{name}"
end
end
person = Person.new
person.name = "Dennis"
puts person.greeting
En el código anterior, establecemos el nombre llamando al método attr_accessor setter usando person.name, en lugar de establecer los valores al inicializar el objeto.
Ambos "métodos" de hacer este trabajo, pero inicializar nos ahorra tiempo y líneas de código.
Este es el único trabajo de inicializar. No se puede llamar a initialize como método. Para conseguir realmente los valores de un objeto de instancia deberá utilizar getters y setters (attr_reader (get), attr_writer(set), y attr_accessor(ambos)). Vea a continuación para más detalles sobre ellos.
Getters, Setters (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: Todo el propósito de un getter es devolver el valor de una variable de instancia en particular. Visite el siguiente código de ejemplo para obtener un desglose al respecto.
class Item
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
def item_name
@item_name
end
def quantity
@quantity
end
end
example = Item.new("TV",2)
puts example.item_name
puts example.quantity
En el código anterior está llamando a los métodos "item_name" y "quantity" en la instancia de Item "example". El " pone ejemplo.item_name" y "ejemplo.quantity "devolverá (o "get") el valor de los parámetros que se pasaron al "ejemplo" y los mostrará en la pantalla.
Afortunadamente en Ruby hay un método inherente que nos permite escribir este código de manera más sucinta; el método attr_reader. Véase el código que figura a continuación;
class Item
attr_reader :item_name, :quantity
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
end
item = Item.new("TV",2)
puts item.item_name
puts item.quantity
Esta sintaxis funciona exactamente de la misma manera, sólo que nos ahorra seis líneas de código. Imagina si tuvieras 5 estado más atribuible a la clase de Artículo? El código se alargaría rápidamente.
Setters, attr_writer: Lo que me cruzó al principio con los métodos setter es que a mis ojos parecía realizar una función idéntica al método initialize. A continuación explico la diferencia basada en mi comprensión;
Como se indicó anteriormente, el método initialize le permite establecer los valores para una instancia de un objeto tras otro creación.
Pero, ¿qué pasa si desea establecer los valores más tarde, después de que se creó la instancia, o cambiarlos después de que se hayan inicializado? Este sería un escenario en el que se utilizaría un método setter. ESA ES LA DIFERENCIA. No tiene que "establecer" un estado particular cuando está utilizando el método attr_writer inicialmente.
El siguiente código es un ejemplo del uso de un método setter para declarar el valor item_name para esta instancia de la clase Item. Note que continuamos utilice el método getter attr_reader para que podamos obtener los valores e imprimirlos en la pantalla, en caso de que desee probar el código por su cuenta.
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
El siguiente código es un ejemplo de uso de attr_writer para acortar nuevamente nuestro código y ahorrarnos tiempo.
class Item
attr_reader :item_name
attr_writer :item_name
end
item = Item.new
puts item.item_name = "TV"
El siguiente código es una reiteración del ejemplo de inicializar anterior de donde estamos usando initialize para establecer el valor de los objetos item_name en el momento de la creación.
class Item
attr_reader :item_name
def initialize(item_name)
@item_name = item_name
end
end
item = Item.new("TV")
puts item.item_name
Attr_accessor: Realiza las funciones de ambos attr_reader y attr_writer, ahorrándote una línea más de código.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-05 00:12:45
Creo que parte de lo que confunde a los nuevos rubistas/programadores (como yo) es:
"¿Por qué no puedo simplemente decirle a la instancia que tiene cualquier atributo dado (por ejemplo, nombre) y darle a ese atributo un valor todo de una sola vez?"
Un poco más generalizado, pero así es como hizo clic para mí:
Dado:
class Person
end
No hemos definido a Person como algo que puede tener un nombre o cualquier otro atributo para el caso.
Así que si entonces:
baby = Person.new
...y tratar de dales un nombre...
baby.name = "Ruth"
Obtenemos un error porque, en Rubyland, una clase Person de objeto no es algo que esté asociado o sea capaz de tener un "nombre" ... ¡todavía!
PERO podemos usar cualquiera de los métodos dados (ver respuestas anteriores) como una forma de decir, "Una instancia de una clase Person (baby
) ahora puede tener un atributo llamado 'nombre', por lo tanto, no solo tenemos una forma sintáctica de obtener y establecer ese nombre, sino que tiene sentido para nosotros hacer tan."
Nuevamente, golpeando esta pregunta desde un ángulo ligeramente diferente y más general, pero espero que esto ayude a la siguiente instancia de Persona de clase que encuentre su camino a este hilo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-26 01:24:36
Si está familiarizado con el concepto OOP, debe estar familiarizado con el método getter y setter. attr_accessor hace lo mismo en Ruby.
Getter y Setter en General
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
Método Setter
def name=(val)
@name = val
end
Método Getter
def name
@name
end
Método Getter y Setter en Ruby
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-04 14:59:39
La mayoría de las respuestas anteriores usan código. Esta explicación intenta responder sin usar ningún código:
Explicación por analogía
Las partes externas no pueden acceder a los secretos internos de la CIA
Imaginemos un lugar realmente secreto: la CIA. Nadie sabe lo que está pasando en la CIA aparte de la gente dentro de la CIA. En otras palabras, las personas externas no pueden acceder a ninguna información en la CIA. Pero porque no es bueno tener una organización que es completamente secreto, cierta información está disponible para el mundo exterior, solo cosas que la CIA quiere que todos sepan, por supuesto: por ejemplo, el Director de la CIA, qué tan amigable con el medio ambiente se compara este departamento con todos los demás departamentos gubernamentales, etc. Otra información: por ejemplo, quiénes son sus agentes encubiertos en Irak o Afganistán-este tipo de cosas probablemente permanecerán en secreto durante los próximos 150 años.
Si estás fuera de la CIA sólo puedes acceder la información que haya puesto a disposición del público. O para usar el lenguaje de la CIA, solo puede acceder a la información que está "despejada".
La información que la CIA quiere poner a disposición del público en general fuera de la CIA se llama: atributos.
El significado de leer y escribir atributos:
En el caso de la CIA, la mayoría de los atributos son de "solo lectura". Esto significa que si usted es un partido externo a la CIA, puedes preguntar: "¿quién es el director de la CIA?"y obtendrás una respuesta directa. Pero lo que no puede hacer con atributos de "solo lectura" es hacer cambios en la CIA. por ejemplo, no puedes hacer una llamada telefónica y de repente decidir que quieres que Kim Kardashian sea la Directora, o que quieres que Paris Hilton sea el Comandante en Jefe.
-
Si los atributos le dieron acceso de "escritura", entonces podría hacer cambios si lo desea, incluso si lo estuviera fuera. De lo contrario, lo único que puedes hacer es leer.
En otras palabras, los accesores le permiten realizar consultas, o realizar cambios, a organizaciones que de otro modo no permiten la entrada de personas externas, dependiendo de si los accesores son de lectura o escritura.
Los objetos dentro de una clase pueden acceder fácilmente entre sí
- Por otro lado, si ya estuvieras dentro de la CIA, entonces podrías llamar fácilmente a tu agente de la CIA en Kabul y pregúntale si quiere tomar una cerveza con el informante local de Kabul después del trabajo. Pero si estás fuera de la CIA, simplemente no se te dará acceso: no podrás saber quiénes son (acceso de lectura), y no podrás cambiar su misión (acceso de escritura).
Exactamente lo mismo con las clases y su capacidad para acceder a variables, propiedades y métodos dentro de ellas. HTH! Cualquier pregunta, por favor pregunte y espero poder aclarar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-15 13:56:04
Simplemente definirá un setter y un getter para la clase.
Tenga en cuenta que
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
So
attr_accessor :v which means
attr_reader :v; attr_writer :v
Son equivalentes para definir un setter y un getter para la clase.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-12 08:30:42
Simplemente attr-accessor
crea los métodos getter
y setter
para los atributos especificados
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-17 11:05:49
Otra forma de entenderlo es averiguar qué código de error elimina al tener attr_accessor
.
Ejemplo:
class BankAccount
def initialize( account_owner )
@owner = account_owner
@balance = 0
end
def deposit( amount )
@balance = @balance + amount
end
def withdraw( amount )
@balance = @balance - amount
end
end
Los siguientes métodos están disponibles:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
Los siguientes métodos arrojan error:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
owner
y balance
no son, técnicamente, un método, sino un atributo. La clase BankAccount no tiene def owner
y def balance
. Si lo hace, entonces puede usar los dos comandos a continuación. Pero esos dos métodos no están ahí. Sin embargo, usted puede access atributos como si access un método a través de attr_accessor
!! De ahí la palabra attr_accessor
. Atributo. Accessor. Accede a atributos como accederías a un método.
Agregar attr_accessor :balance, :owner
le permite leer y escribir balance
y owner
"método". Ahora puedes usar los últimos 2 métodos.
$ bankie.balance
$ bankie.owner
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 18:26:41
Define un atributo con nombre para este módulo, donde el nombre es symbol.id2name, creando una variable de instancia (@name) y un método de acceso correspondiente para leerla. También crea un método llamado name= para establecer el atributo.
module Mod
attr_accessor(:one, :two)
end
Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-11 16:12:37
Para resumir un atributo accessor aka attr_accessor le da dos métodos libres.
Como en Java se llaman getters y setters.
Muchas respuestas han mostrado buenos ejemplos, así que voy a ser breve.
# the_attribute
Y
# the_attribute =
En los antiguos documentos de ruby una etiqueta hash # significa un método. También podría incluir un prefijo de nombre de clase... MyClass # my_method
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-14 03:56:47
Atributos y métodos de acceso
Los atributos son componentes de clase a los que se puede acceder desde fuera del objeto. Se conocen como propiedades en muchos otros lenguajes de programación. Sus valores son accesibles usando la "notación de puntos", como en nombre_objeto.attribute_name. A diferencia de Python y algunos otros lenguajes, Ruby no permite acceder a variables de instancia directamente desde fuera del objeto.
class Car
def initialize
@wheels = 4 # This is an instance variable
end
end
c = Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
En el ejemplo anterior, c es una instancia (objeto) de la clase Car. Intentamos sin éxito leer el valor de la variable de instancia wheels desde fuera del objeto. Lo que sucedió es que Ruby intentó llamar a un método llamado wheels dentro del objeto c, pero no se definió dicho método. En resumen, object_name.attribute_name intenta llamar a un método llamado attribute_name dentro del objeto. Para acceder al valor de la variable wheels desde el exterior, necesitamos implementar un método de instancia con ese nombre, que devolverá el valor de esa variable cuando se llame. Eso es llamado método de accessor. En el contexto de programación general, la forma habitual de acceder a una variable de instancia desde fuera del objeto es implementar métodos de acceso, también conocidos como métodos getter y setter. Un getter permite que el valor de una variable definida dentro de una clase se lea desde el exterior y un setter permite que se escriba desde el exterior.
En el siguiente ejemplo, hemos agregado los métodos getter y setter a la clase Car para acceder a la variable wheels desde fuera del objeto. Esta no es la" forma Ruby " de definir getters y setters; solo sirve para ilustrar lo que hacen los métodos getter y setter.
class Car
def wheels # getter method
@wheels
end
def wheels=(val) # setter method
@wheels = val
end
end
f = Car.new
f.wheels = 4 # The setter method was invoked
f.wheels # The getter method was invoked
# Output: => 4
El ejemplo anterior funciona y código similar se usa comúnmente para crear métodos getter y setter en otros lenguajes. Sin embargo, Ruby proporciona una forma más sencilla de hacer esto: tres métodos integrados llamados attr_reader, attr_writer y attr_cessor. El método attr_reader hace que una variable de instancia sea legible desde el exterior, attr_writer la hace escribible, y attr_cessor lo hace legible y escribible.
El ejemplo anterior se puede reescribir así.
class Car
attr_accessor :wheels
end
f = Car.new
f.wheels = 4
f.wheels # Output: => 4
En el ejemplo anterior, el atributo wheels será legible y escribible desde fuera del objeto. Si en lugar de attr_accessor, usáramos attr_reader, sería de solo lectura. Si usamos attr_writer, sería solo escritura. Esos tres métodos no son getters y setters en sí mismos, pero, cuando se llaman, crean métodos getter y setter para nosotros. Son métodos que dinámicamente (programáticamente) generar otros métodos; eso se llama metaprogramación.
El primer ejemplo (más largo), que no emplea los métodos integrados de Ruby, solo debe usarse cuando se requiere código adicional en los métodos getter y setter. Por ejemplo, un método setter puede necesitar validar datos o hacer algún cálculo antes de asignar un valor a una variable de instancia.
Es posible acceder (leer y escribir) variables de instancia desde fuera del objeto, utilizando el instance_variable_get y instance_variable_set métodos integrados. Sin embargo, esto rara vez es justificable y generalmente es una mala idea, ya que evitar la encapsulación tiende a causar todo tipo de estragos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-05 11:41:58
Hmmm. Muchas buenas respuestas. Aquí están mis centavos.
attr_accessor
es un método simple que nos ayuda en la limpieza (SECADO ) hasta el repitiendogetter and setter
métodos.Para que podamos centrarnos más en escribir lógica de negocios y no preocuparnos por los setters y getters.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-29 09:50:08
La funcionalidad principal de attr_accessor sobre los otros es la capacidad de acceder a los datos de otros archivos.
Así que normalmente tendrías attr_reader o attr_writer pero la buena noticia es que Ruby te permite combinar estos dos junto con attr_accessor. Pienso en ello como mi método para ir porque es más redondeado o versátil.
Además, peep en mente que en Rails, esto se elimina porque lo hace por ti en el back-end. Así que en otras palabras: mejor usar attr_cessor sobre los otros dos porque no tienes que preocuparte por ser específico, el accessor lo cubre todo. Sé que esto es más una explicación general, pero me ayudó como principiante.
Espero que esto haya ayudado!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-17 15:40:55