Clases en Ruby vs Clases en Java

En Java era así: Uno se vestía con una túnica de color azafrán, se rapaba la cabeza, prendía un poco de velas y varillas de incienso, para después empezar con el mantra "La Clase es el Tipo del Objetoooooo, La Clase es el Tipo del Objetoooooo, La Clase es el Tipo del Objetoooooo, ..."

En Ruby las clases no son tipos, los objetos son tan, pero taaaan plásticos que en realidad la mejor aproximación a saber de que tipo es un objeto es explorar su comportamiento, lo que ha llevado a definir el "Duck Typing". Si el objeto camina como un pato, vuela como un pato, y suena como un pato, entonces no es un objeto Java porque no se parece a Duke ;-)

Esto se refleja en cosas como el método method_missing de la clase Object (raíz de la muy "chata" jerarquía de clases de Ruby) que es invocado cuando un objeto recibe un mensaje que no sabe como manejar, y que permite hace cosas como:

class Pato
  def method_missing( id_metodo )
    metodo_invocado = id_metodo.id2name
    metodo_invocado.length if metodo_invocado =~ /cua*c/
  end
end 
de_goma = Pato.new
puts de_goma.cuac      # -> 4
puts de_goma.cuaac    # -> 5
puts de_goma.cuaaac  # -> 6

Que es una clase que responde dinámicamente (devolviendo la longitud de los mensajes "cuac" que le pasan) a un mensaje para el que no encuentra un método definido en forma explícita en ella. El potencial a nivel de Domain Specific Languages está muy bien explicado por Jim Weirich en su presentación del para el RubyConf Speaking the Lingo: Creating Domain Specific Languages in Ruby, el podcast está en Odeo y es burda de ameno.

Una de esas cosas extrañas en Ruby cuando uno viene de Java es que las clases no tienen mucho de particular, empezando con que una clase en Ruby es sencillamente una constante que referencia a un objeto de la clase Class, que por cierto no tiene ni media docena de métodos.

Cuando por algún motivo intentas usar una clase y esta no se encuentra definida, lo que se obtiene es un: uninitialized constant que por supuesto uno no entiende de que va.

La clase Class extiende de Module que es básicamente una colección de métodos y constantes, y que cuando se viene del mundo Java uno intenta reconciliar erróneamente con un Package.

De forma análoga un Módulo en Ruby también es una constante que referencia a un objeto de la clase Module (que si es un hierro), y tiene una vago parecido "funcional" a las interfaces en Java, ya que los módulos en Ruby permiten añadir funcionalidad a un clase sin tener que recurrir a la herencia, ya que en Ruby tampoco existe la herencia múltiple.

En Ruby se utiliza un mecanismo llamado mixin que permite obtener acceso a las constantes, variables de clase y métodos de instancia del módulo que se incluye.

La ventaja de los Módulos Ruby sobre las Interfaces Java para obtener comportamientos predefinidos, es que cuando haces un include de un Module no piensas ¡Cooooooño tengo que implementar tooooooodo ese poco de métodos! Que fastidioooooo....

Cuando uno entiende que el código dentro de una Clase o Módulo Ruby es sencillamente código ejecutable entonces es cuando se da cuenta de porque Java parecia una cómoda y segura camisa de fuerza en lo que a orientación a objetos se refiere, ya que manipular las clases se hace extremadamente natural y por ejemplo cambia un método de privado a público es tan sencillo como:

class MiClase
  def metodo_publico
    "hola"
  end
  private
  def metodo_privado
    "adios"
  end 
end

o = MiClase.new

begin
  puts "Va a generar un error"
  puts o.metodo_publico
  puts o.metodo_privado
rescue
  puts $!
end

class MiClase
  public(:metodo_privado)
end 

begin
  puts "Ya el método es público"
  puts o.metodo_publico
  puts o.metodo_privado
rescue
  puts $!
end

Lo que genera la salida:

Va a generar un error
hola
private method 'metodo_privado' called for #<miclase :0x2bd0da0>
Ya el método es público
hola
adios

La variable $! es un perlismo (en vías de extinción por lo que entiendo) en Ruby, y sencillamente referencia la última excepción que se generó. Y ojo, los métodos public y private son privados, el bochinche tampoco es taaaan así ;-)

Un concepto que existe en Java (pero se usa poco en mi experiencia) es el de la Clase Anónima (Anonymous Class) (Singleton Class) que en Ruby surge por todos lados, y se evidencia cuando se manipula el comportamiento de un objeto específico y no la clase a la que está asociado:

lenguaje = "Java"
original = lenguaje.dup

class <<lenguaje
  def to_s
    "#{self} :-("
  end   
end

puts lenguaje.class  # -> String
puts lenguaje.to_s  # ->  Java :-(
puts original.class   # ->  String
puts original.to_s   # ->  Java

El método to_s de Ruby es equivalente al toString de Java, fíjense como ambas variables reportan que su clase es String, pero sólo en una hemos alterado el comportamiento de método to_s.

Ahora, el método to_s pertenece a la clase Object de Ruby, y como en Ruby las clases nunca están cerradas, yo puedo darle una navaja al mono redefiniendo ese método ahí mismo con algo como:

o = Object.new

puts o.to_s # -> #object :0x2bd1520

class Object
  alias to_s_ANTERIOR to_s
  def to_s
    "*** #{to_s_ANTERIOR} ***"
  end
end   

puts o.to_s # -> *** #object :0x2bd1520 ***

Cosa, que en Java sería blasfemia por motivos de seguridad, que es reforzada por la propia jerarquía de los Classloaders, etc ¿Cómo les quedó el ojo? Parafraseando el nombre de un popular libro de Zen, en Ruby "Nada Sagrado" ;-)


2 Respuestas a “Clases en Ruby vs Clases en Java”

  1. 1 AVATAR

    Muy buena la explicacion.

    Esta barbaro poder entender un poco mas la flexibilidad de ruby con ejemplos claros como los diste

    Gracias y esperemos ver mas!!!

  2. 2 elkami

    Jojojojo si ciertamente java tiene sus detalles y como por ahi decia un conocido es un lenguaje que sacaron y fueron parchando con el tiempo, parchando por aqui y por aca lo que termino en un masacote todo medio planeado. A mi en lo personal me gusta Java y era el lenguaje que usaba, ahorita por el trabajo aprendi y estoy usando Ruby y ROR, la verdad que es muy bueno =D me a gustado bastante aunque todavia no lo domino a la perfeccion =P, pero aun asi me sigue gustando Java.

    JAVA FOR EVER ahhh I

Añade un Comentario





RSS feeds

Suscríbete a nuestros RSS Feeds