¿Sabes cómo puedes usar los atributos con Ruby?

Utilización de atributos

Mira cualquier código orientado a objetos y todo sigue más o menos el mismo patrón. Cree un objeto, llame a algunos métodos en ese objeto y acceda a los atributos de ese objeto. No hay mucho más que puedas hacer con un objeto excepto pasarlo como parámetro al método de otro objeto. Pero lo que nos preocupa aquí son los atributos.

 

Los atributos son como variables de instancia a las que se puede acceder a través de la notación de punto de objeto. Por ejemplo, person.name accedería al nombre de una persona. Del mismo modo, a menudo se pueden asignar atributos como person.name = "Alice". Esta es una característica similar a las variables de los miembros (como en C++), pero no es lo mismo. No hay nada especial aquí, los atributos se implementan en la mayoría de los lenguajes usando "getters" y "setters", o métodos que recuperan y establecen los atributos de las variables de instancia.

Ruby no hace una distinción entre getters y setters de atributos y métodos normales. Debido al método flexible de Ruby de llamar a la sintaxis, no es necesario hacer ninguna distinción. Por ejemplo, person.name y person.name() son la misma cosa, estás llamando al método de nombre con cero parámetros. Una parece una llamada a un método y la otra parece un atributo, pero ambas son realmente la misma cosa. Ambos están llamando por su nombre al método. De forma similar, cualquier nombre de método que termine en un signo igual (=) puede utilizarse en una asignación. La sentencia person.name = "Alice" es realmente lo mismo que person.name=(alice), aunque hay un espacio entre el nombre del atributo y el signo de igualdad, sigue llamando a name= method.

Implementación de los atributos usted mismo

Usted mismo puede implementar fácilmente los atributos. Definiendo los métodos setter y getter, puede implementar cualquier atributo que desee. Aquí hay un código de ejemplo que implementa el atributo name para una clase de persona. Almacena el nombre en una variable de instancia @name, pero el nombre no tiene que ser el mismo. Recuerde, no hay nada especial en estos métodos.

 #!/usr/bin/env ruby class Person def initialize(name) @name = name end def name @name end def name=(name) @name = name end def say_hello puts "Hello, #{@name}" end end

 

Una cosa que notará de inmediato es que esto es mucho trabajo. Es mucho escribir sólo para decir que quieres un atributo llamado nombre que acceda a la variable de instancia @name. Afortunadamente, Ruby proporciona algunos métodos de conveniencia que definirán estos métodos para usted.

 

Usando attr_reader, attr_writer y attr_accessor

Hay tres métodos en la clase Module que puede utilizar dentro de sus declaraciones de clase. Recuerde que Ruby no hace distinción entre runtime y "compile time", y cualquier código dentro de las declaraciones de clase puede no sólo definir métodos sino también métodos de llamada. Llamar a los métodos attr_reader, attr_writer y attr_accessor definirá a su vez los setters y getters que estábamos definiendo nosotros mismos en la sección anterior.

El método attr_reader hace lo que parece que va a hacer. Toma cualquier número de parámetros de símbolo y, para cada parámetro, define un método "getter" que devuelve la variable de instancia del mismo nombre. Por lo tanto, podemos reemplazar nuestro método de nombre en el ejemplo anterior con attr_reader :name.

 

Del mismo modo, el método attr_writer define un método "setter" para cada símbolo que se le pasa. Tenga en cuenta que el signo igual no tiene por qué ser parte del símbolo, sólo el nombre del atributo. Podemos reemplazar el método name= del ejemplo anterior con una llamada a attr_writier :name.

 

Y, como era de esperar, attr_accessor hace el trabajo de attr_writer y attr_reader. Si necesita tanto un setter como un getter para un atributo, es práctica común no llamar a los dos métodos por separado, y en su lugar llamar a attr_accessor. Podríamos reemplazar tanto el nombre como los métodos name= del ejemplo anterior con una sola llamada a attr_accessor :name.

 #!/usr/bin/env ruby def person attr_accessor :name def initialize(name) @name = name end def say_hello puts "Hello, #{@name}" end end

 

¿Por qué definir manualmente a los fijadores y a los receptores?

¿Por qué se deben definir las máquinas de incubación manualmente? ¿Por qué no usar los métodos attr_* cada vez? Porque rompen la encapsulación. La encapsulación es el principio que establece que ninguna entidad externa debe tener acceso ilimitado al estado interno de sus objetos. Se debe acceder a todo mediante una interfaz que evite que el usuario corrompa el estado interno del objeto. Usando los métodos anteriores, hemos perforado un gran agujero en nuestra pared de encapsulación y hemos permitido que se establezca absolutamente cualquier cosa para un nombre, incluso nombres obviamente inválidos.

 

Una cosa que verá a menudo es que attr_reader se usará para definir rápidamente un getter, pero un setter personalizado se definirá ya que el estado interno del objeto a menudo quiere ser leído directamente desde el estado interno. A continuación, el ajustador se define manualmente y realiza verificaciones para garantizar que el valor que se está configurando tiene sentido. O, tal vez más comúnmente, no se define a ningún fijador en absoluto. Los otros métodos en la función de clase establecen la variable de instancia detrás del getter de alguna otra manera.

Ahora podemos añadir una edad e implementar correctamente un atributo de nombre. El atributo age puede ser establecido en el método constructor, leído usando el buscador de edad pero sólo manipulado usando el método have_birthday, que incrementará la edad. El atributo name tiene un getter normal, pero el setter se asegura de que el nombre está en mayúsculas y está en forma de Nombre Apellido.

 

 #!/usr/bin/env ruby class Person def initialize(name, age) self.name = name @age = age end attr_reader :name, :age def name=(new_name) if new_name =~ /^[A-Z][a-z]+ [A-Z][a-z]+$/ @name = new_name else puts "'#{new_name}' is not a valid name!" end end def have_birthday puts "Happy birthday #{@name}!" @age += 1 end def whoami puts "You are #{@name}, age #{@age}" end end p = Person.new("Alice Smith", 23) # Who am I? p.whoami # She got married p.name = "Alice Brown" # She tried to become an eccentric musician p.name = "A" # But failed # She got a bit older p.have_birthday # Who am I again? p.whoami

(0 votes)