Clases y Objetos

Desde hace tiempo el estilo de programación funcional (que se usa por ejemplo en el lenguaje C) es usado para programar. En este tipo de programación, hay que centrarse en los pasos para realizar la tarea, y nos olvidamos de como se manejan los datos.

Sin embargo, en la programación orientada a objetos, los objetos son los agentes, el universo de tu programa: se presta atención a la estructura de los datos. Cuando se diseña una clase, se piensa en los objetos que serán creados por esa clase: en las cosas que podrá hacer ese objeto, y las características que lo definen.

Un objeto es un contenedor de datos, que a su vez controla el acceso a dichos datos. Asociados a los objetos está una serie de variables que lo definen: sus atributos. Y también un conjunto de funciones que crean un interfaz para interactuar con el objeto: son los métodos.

Un objeto es una combinación de estado y de métodos que cambian ese estado.

Una clase es usada para construir un objeto. Una clase es como un molde para objetos. Y un objeto, una instancia de la clase. Por ejemplo, se puede usar la clase Button para hacer docenas de botones, cada botón con su propio color, tamaño, forma,…

Nuestra primera clase

# define la clase Perro  
class Perro  
 
  # método inicializar clase
  def initialize(raza, nombre)  
    # atributos   
    @raza = raza  
    @nombre = nombre  
  end  
 
  # método ladrar
  def ladrar
    puts 'Guau! Guau!'  
  end  
 
  # método saludar
  def saludar
    puts "Soy un perro de la raza #{@raza} y mi nombre es #{@nombre}"  
  end  
end  
 
# para hacer nuevos objetos,
# se usa el método new
d = Perro.new('Labrador', 'Benzy')  
puts d.methods.sort  
puts "La id del ojbeto es #{d.object_id}."  
 
if d.respond_to?("correr")  
  d.correr  
else  
  puts "Lo siento, el objeto no entiende el mensaje 'correr'"  
end  
 
d.ladrar
d.saludar  
 
# con esta variable, apuntamos al mismo objeto  
d1 = d  
d1.saludar
 
d = nil  
d1.saludar

El método new se usa para crear un nuevo objeto de la clase Perro. Los objetos son creados en el momento y el espacio de memoria donde se guardan, se asigna a una variable, en este caso la variable d, que se conoce como variable de referencia.

Un método recién creado no es un espacio en blanco: un objeto recién creado, puede responder un montón de mensajes. Para ver la lista de esos mensajes o métodos de forma ordenada (.sort):

puts d.methods.sort

El resultado es una lista de todos los mensajes o métodos que el objeto recién creado puede responder. De todos esos métodos, los object_id y respond_to? son importantes.

object_id, respond_to?

Cada objeto en Ruby tiene un único número asociado con él. Se puede ver dicho número mediante el método object_id. En nuestro ejemplo:

puts "El número que identifica al objeto denotado por la variable d es #{d.object_id}."

Se puede conocer de antemano, si un objeto será capaz de responder a un mensaje; o dicho de otra forma, si un objeto posee cierto método. Para ello se usa respond_to?. En nuestro ejemplo:

if d.respond_to?("correr")  
  d.correr  
else  
  puts "Lo siento, el objeto no entiende el mensaje 'correr'"  
end

class, instance_of?

Puedes saber a qué clase pertenece un objeto mediante el método class. En nuestro ejemplo si ponemos:

d = Perro.new('Alsatian', 'Lassie')  
puts d.class.to_s # obtenemos Perro

instance_of? nos devuelve true si un objeto es instancia de una clase determinada. Por ejemplo:

num = 10  
puts (num.instance_of? Fixnum) # true

La clase Class

En este diagrama se vió como todas las clases descendían de la clase Class.

Las clases en Ruby son instancias de la clase Class. Cuando se define una nueva clase (p.e. class NombreClase … end), se crea un objeto de la clase Class y es asignado a una constante (en este caso NombreClase). Cuando se usa NombreClase.new para construir un nuevo objeto, se usa el método de la clase Class para crear nuevas instancias; y después se usa el método inicializador de la propia clase NombreClase: la construcción y la inicialización de un objeto son cosas distintas, y pueden modificarse.

Constructores literales

Significa que se puede usar una notación especial, en vez de usar new para crear un nuevo objeto de esa clase. Las clases que un constructor literal puede crear, están en la siguiente tabla: cada vez que usas uno de estos constructores, creas un nuevo objeto.

Clase Constructor Literal Ejemplo
String ' ó " "nuevo string" o 'nuevo string'
Símbolo : :símbolo ó :"símbolo con espacios"
Array [ ] [1, 2, 3, 4, 5]
Hash { } {"Nueva Yor" => "NY", "Oregon" => "OR"}
Rango .. ó … 0…10 ó 0..9
Expresiones regulares / /([a-z]+)/

Por esto, y aunque a veces no lo parezca, siempre estamos creando objetos. En Ruby, todo es un objeto.

Reciclado de basura

La instrucción:

d = nil

hace que d apunte a nil, lo que significa que no se refiere a nada. Si después de eso, añado:

d1 = nil

entonces el objeto Perro dejará de estar apuntado por las variables y será objetivo del reciclado de basura. El reciclado de basura de Ruby es del tipo marcar-y-borrar (mark-and-sweep):

  • en la fase "mark" el programa que recicla la memoria, verifica si el objeto está en uso. Si un objeto es apuntado por una variable, podría ser usado, y por tanto ese objeto se marca para ser conservado.
  • si no hay variable que apunte al objeto, entonces el objeto no es marcado. Y en la fase "sweep" se borran los objetos en desuso para liberar memoria de modo que pueda volver a ser utilizada por el intérprete de ruby.

Ruby usa un mark-and-sweep conservador: no hay garantía de que un objeto sea eliminado por el colector, antes de que termine el programa. Si almacenas algo en un array, y se mantiene el array, todo dentro del array es marcado. Si almacenas algo en una constante o variable global, entonces se marca para siempre.

Métodos de clase

La idea de los métodos de clase es mandar el mensaje a la clase, en vez de una de sus instancias. Los métodos de clase se usan porque algunas operaciones que pertenecen a una clase, no pueden ser realizadas por sus instancias. new es un buen ejemplo. La tarea de crear nuevos objetos sólo la puede hacer la clase; los objetos no pueden crearse a sí mismos.

Si no se indica lo contrario, el contenido de esta página se ofrece bajo Creative Commons Attribution 3.0 License