tutorial - ruby wikipedia




¿Qué es attr_accessor en ruby? (12)

Estoy teniendo dificultades para entender attr_accessor en Ruby. ¿Puede alguien explicarme esto?


Atributos y métodos de acceso

Los atributos son componentes de clase a los que se puede acceder desde fuera del objeto. Son conocidos como propiedades en muchos otros lenguajes de programación. Se puede acceder a sus valores utilizando la "notación de puntos", como en object_name.attribute_name. A diferencia de Python y algunos otros lenguajes, Ruby no permite acceder a las 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 de ruedas desde fuera del objeto. Lo que sucedió es que Ruby intentó llamar a un método llamado ruedas dentro del objeto c, pero no se definió tal 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 de las ruedas desde el exterior, necesitamos implementar un método de instancia con ese nombre, que devolverá el valor de esa variable cuando se llame. Eso se llama un método de acceso. 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 de obtención y establecimiento. Un captador permite que el valor de una variable definida dentro de una clase se lea desde el exterior y un configurador permite que se escriba desde el exterior.

En el siguiente ejemplo, hemos agregado métodos de captador y definidor a la clase Coche para acceder a la variable de las ruedas desde fuera del objeto. Esta no es la "forma de Ruby" de definir a los getters y setters; solo sirve para ilustrar lo que hacen los métodos de captador y definidor.

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 un código similar se usa comúnmente para crear métodos de obtención y establecimiento en otros idiomas. Sin embargo, Ruby proporciona una forma más sencilla de hacer esto: tres métodos incorporados llamados attr_reader, attr_writer y attr_acessor. El método attr_reader hace que una variable de instancia sea legible desde el exterior, attr_writer hace que se pueda escribir, y attr_acessor lo hace legible y se puede escribir.

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 ruedas se podrá leer y escribir desde fuera del objeto. Si en lugar de attr_accessor, usáramos attr_reader, sería de solo lectura. Si utilizamos attr_writer, sería de solo escritura. Esos tres métodos no son captadores y definidores en sí mismos, sino que, cuando se les llama, crean métodos para ellos. Son métodos que dinámicamente (programáticamente) generan otros métodos; Eso se llama metaprogramación.

El primer ejemplo (más largo), que no emplea los métodos incorporados de Ruby, solo debe usarse cuando se requiere un código adicional en los métodos de obtención y configuración. Por ejemplo, un método de establecimiento 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 los métodos incorporados instance_variable_get y instance_variable_set. Sin embargo, esto rara vez es justificable y, por lo general, es una mala idea, ya que el hecho de evitar la encapsulación tiende a causar todo tipo de estragos.


Básicamente, falsifican atributos de datos de acceso público, que Ruby no tiene.


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 leerlo. También crea un método llamado nombre = para establecer el atributo.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]

Digamos que tienes una Person clase.

class Person
end

person = Person.new
person.name # => no method error

Obviamente nunca definimos el name método. Vamos a hacer eso.

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

Ajá, 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 . No creamos al escritor todavía, así que hagamos eso.

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"

Increíble. Ahora podemos escribir y leer la variable de instancia @name usando métodos de lector y escritor. 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 quiera que tanto el lector como el escritor solo utilicen 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 de persona se establecerá como cuando lo hicimos manualmente, para que puedas usarla 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. Para entender cómo los attr_reader , attr_writer y attr_accessor realmente generan métodos para usted, lea otras respuestas, libros, documentos ruby.


Es solo un método que define los métodos getter y setter para las variables de instancia. Una implementación de ejemplo 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

Hmmm Muchas buenas respuestas. Aquí están mis pocos centavos.

  • attr_accessor es un método simple que nos ayuda a limpiar ( SECAR ) los métodos repetidores de getter and setter .

  • Para que podamos centrarnos más en escribir lógica de negocios y no preocuparnos por los instaladores y captadores.


La mayoría de las respuestas anteriores utilizan código. Esta explicación intenta responderla sin usar ningún código:

Explicación vía 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á sucediendo en la CIA aparte de las personas dentro de la CIA. En otras palabras, las personas externas no pueden acceder a ninguna información en la CIA. Pero como no es bueno tener una organización que sea completamente secreta, cierta información está disponible para el mundo exterior, solo las cosas que la CIA quiere que todos conozcan, por ejemplo: el Director de la CIA, qué tan amigable para el medio ambiente es este departamento. a 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 se mantendrá en secreto durante los próximos 150 años.

  • Si está fuera de la CIA, solo puede acceder a la información que ha puesto a disposición del público. O, para usar el lenguaje de la CIA, solo puede acceder a la información que está "borrada".

  • La información que la CIA quiere poner a disposición del público en general fuera de la CIA se denomina atributos.

El significado de los atributos de lectura y escritura:

  • En el caso de la CIA, la mayoría de los atributos son "solo lectura". Esto significa que si usted es una parte ajena a la CIA, puede preguntar: "¿quién es el director de la CIA?" y obtendrás una respuesta directa. Pero lo que no puede hacer con los atributos de "solo lectura" es hacer cambios en la CIA. por ejemplo, no puede hacer una llamada telefónica y de repente decide que desea que Kim Kardashian sea el Director, o que desea 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 estuviera afuera. 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 el acceso de personas externas, según si los accesores son de acceso de lectura o de escritura.

Los objetos dentro de una clase pueden acceder fácilmente entre sí

  • Por otro lado, si ya estaba dentro de la CIA, podría llamar fácilmente a su agente de la CIA en Kabul y preguntarle si quiere tomar una cerveza con el informante local de Kabul después del trabajo. Pero si está fuera de la CIA, simplemente no se le dará acceso: no podrá saber quiénes son (acceso de lectura), y no podrá 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.


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 el balance no son, técnicamente, un método , sino un atributo. La clase BankAccount no tiene def owner def balance 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, puede acceder a los atributos como si tuviera acceso a un método a través de attr_accessor !! De ahí la palabra attr_accessor . Atributo. Accesorio Accede a atributos como usted accedería a un método.

Agregando attr_accessor :balance, :owner permite leer y escribir balance y el "método" de owner . Ahora puedes usar los 2 últimos métodos.

$ bankie.balance
$ bankie.owner

Si está familiarizado con el concepto OOP, debe estar familiarizado con el método de obtención y configuración. 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"

Simplemente attr-accessor crea los métodos getter y setter para los atributos especificados


attr_accessor es solo un método . (El enlace debe proporcionar más información acerca de cómo funciona: observe los pares de métodos generados y un tutorial le mostrará cómo usarlo).

El truco es que la class no es una definición en Ruby (es "solo una definición" en lenguajes como C ++ y Java), pero 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 "abierto" en este punto.

La necesidad de attr_accessor y amigos, es, bueno:

  1. Ruby, como Smalltalk, no permite el acceso a las variables de instancia fuera de los métodos 1 para ese objeto. Es decir, no se puede acceder a las variables de instancia en la forma xy como es común en, por ejemplo, Java o incluso Python. En Ruby y siempre se toma como un mensaje para enviar (o "método para llamar"). Por lo tanto, los métodos attr_* crean envolturas que representan la instancia del acceso @variable a través de métodos creados dinámicamente.

  2. Caldera chupa

Espero que esto aclare algunos de los pequeños detalles. Feliz codificacion

1 Esto no es estrictamente cierto y hay algunas "técnicas" alrededor de esto , pero no hay soporte de sintaxis para el acceso de "variable de instancia pública".


attr_accessor es (como se indica en @pst) solo un método. Lo que hace es crear más métodos para ti.

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






ruby