Sunday, October 11, 2009

Algo sobre el Lenguaje Ruby (II)

En esta segunda entrega, veremos algo sobre estilos de código en Ruby, y luego algunos ejemplos de programación de objetos básicos en Ruby, basándonos en algunos TPs de la materia Programación III.

Estilos de código:

Hay varias cuestiones a tener en cuenta a la hora de programar en objetos en Ruby. Como en Smalltalk, se sigue la convención de que la clases se definen con mayúscula en la primer letra, las instancias y sus variables con minúscula, así como los métodos.

Las constantes se escriben todo en mayúscula.

La diferencia principal con el estilo “smalltalkero” es que los nombres con mas de una palabra se escriben de manera diferente: Mientras que en Smalltalk una variable o métodos se escribe estoEsElNombreClasicoDeUnaVariableSmalltalk, Ruby tiene por convención que sea esto_es_un_nombre_tipico_en_ruby.

Las convenciones son importantes, dado que todos los métodos, funciones, módulos, clases y demás cosas de las librerías se escriben siguiendo estas reglas, con lo cual, no adaptarnos a ellas puede traer problemas.

Un ultimo detalle es que algunos nombres de métodos en Ruby terminan con el signo '?'. Cada vez que un método termina con el signo de interrogación significa que retorna siempre verdadero o falso. En el caso que el método termine con '!', implica que el objeto al cual le enviamos el mensaje sera modificado. Es como una advertencia de alerta, por decirlo de alguna manera.

Implementaciones y pruebas referidas al TP 2 de Programación III en Ruby

Abrimos nuestro editor de textos preferido y copiamos lo siguiente:

class Persona

# Definimos getters
def get_nombre()
return @nombre
end

def get_apellido()
return @apellido
end

def get_dni()
return @dni
end

def get_padre()
return @padre
end

def get_madre()
return @madre
end

# Definimos setters
def set_nombre(nombre)
@nombre = nombre
end

def set_apellido(apellido)
@apellido = apellido
end

def set_dni(dni)
@dni = dni
end

def set_padre(padre)
@padre = padre
end

def set_madre(madre)
@madre = madre
end

end


Observemos que los getters y los setters son similares, y solo cambia la variable a la que esta definida. Existen métodos dentro de Ruby que permiten automatizar la creacion de setters y getters. Ellos son:

attr_reader: Para creación de getters
attr_writer: Para creación de setters
attr_accessor: Para creación de getters y setters

El código anteriormente presentado se reduciría al siguiente

class Persona
attr_accessor :nombre, :apellido, :dni, :padre, :madre
end

Con esta ultima implementación abrimos un interprete interactivo (irb) y hacemos algunas pruebas(En negrita las lineas ingresadas por el usuario):

$ irb
irb(main):001:0> require 'Personas_con_accesors'

=> true
irb(main):002:0> p = Persona.new()

=> #
irb(main):005:0> p.methods

=> ["inspect", "tap", "clone", "public_methods", "__send__", "object_id", "instance_variable_defined?", "apellido", "equal?", "freeze", "extend", "apellido=", "send", "methods", "hash", "dup", "to_enum", "instance_variables", "dni", "eql?", "instance_eval", "id", "dni=", "singleton_methods", "taint", "enum_for", "frozen?", "instance_variable_get", "instance_of?", "padre", "display", "to_a", "method", "type", "padre=", "instance_exec", "protected_methods", "==", "===", "instance_variable_set", "kind_of?", "madre", "respond_to?", "to_s", "class", "madre=", "private_methods", "=~", "tainted?", "__id__", "nombre", "untaint", "nil?", "is_a?", "nombre="]
irb(main):010:0> p.public_methods(false)

=> ["padre", "madre=", "nombre=", "dni", "padre=", "apellido", "dni=", "madre", "nombre", "apellido="]
irb(main):011:0> p.nombre="Ana"

=> "Ana"
irb(main):012:0> p.apellido="Garcia"

=> "Garcia"
irb(main):013:0> p.dni=33221256

=> 33221256
irb(main):014:0> p.nombre

=> "Ana"
irb(main):015:0> p2 = Persona.new

=> #
irb(main):016:0> p2.nombre="Jose"

=> "Jose"
irb(main):017:0> p2.apellido="Taringa"

=> "Taringa"
irb(main):018:0> p.padre=p2

=> #
irb(main):019:0> p.inspect

=> "#>"
irb(main):020:0> exit

$

Hemos visto hasta aquí la implementación de métodos y clases en sus formas básicas.

Pasemos a definir ahora un método para inicializar el objeto. Sabemos que el método para inicializar un objeto es una función que asigna a las variables de instancia los valores adecuados para que el objeto funcione en el sistema sin problemas. Como todas las variables sin valor se inician con nil, sabemos que no es conveniente para operar, siempre es conveniente tener un mensaje de inicialización de los objetos.

class Persona

attr_accessor :nombre, :apellido, :dni, :padre, :madre

def initialize(nombre, apellido, dni, padre="", madre="")
@nombre = nombre
@apellido = apellido
@dni = dni
@padre = padre
@madre = madre
end
end

Un dato interesante es que el método initialize es automáticamente invocado cuando le enviamos el mensaje new a la clase. No debemos preocuparnos por la inicialización de los objetos una vez que implementamos el método de inicialización.

Si observamos la cabecera del método de inicialización

def initialize(nombre, apellido, dni, padre="", madre="")

vemos que padre y madre se asignan con cadenas vacías. Lo que estamos haciendo es asignar valores por defecto a esas dos variables. O sea, nombre, apellido y dni son obligatorios para crear un objeto de la clase Persona, pero padre y madre son opcionales.

$ irb
irb(main):001:0> require 'Personas_con_accesors_y_mensaje_de_inicializacion'

=> true
irb(main):002:0> p = Persona.new("Jose", "Taringa", 23456876)

=> #
irb(main):003:0> p.padre

=> ""
irb(main):004:0> p2 = Persona.new("Pedro", "Taringa", 14678384)

=> #
irb(main):005:0> p.padre= p2

=> #
irb(main):006:0> p.inspect()

=> "#>"
irb(main):007:0> exit

$

Por ultimo, observemos que la sentencia require se utiliza para importar módulos. Lo que va entre comillas simples es el nombre del archivo que desea importarse. Si encuentra un archivo con ese nombre en la carpeta local, lo carga (como en nuestro ejemplo), sino, busca en la librería estandar de Ruby. Si tampoco lo encuentra allí, lanza un error.

Recursos:

http://www.ruby-lang.org/es/documentation/quickstart/

http://tryruby.hobix.com/

6 comments:

  1. es todo de consola? no hay un entorno de programacion visual?

    ReplyDelete
  2. A que te referis con "entorno de programacion visual"??

    A algo estilo Visual Basic??

    ReplyDelete
  3. Debe estar refiriendose a un IDE, podrias utilizar Eclipse, NetBeans y hasta el gedit.
    Yo utilizo el Gedit y se la re banca, podes agregarle un montón de cosas para hacer mas llevadera la programación (tabular texto, colores de texto, etc)

    Saludos muy bueno el post

    ReplyDelete
  4. Me surgió una duda al leer esto:

    "Las constantes se escriben todo en mayúscula."

    No se escribe unicamente la primera en mayúscula??
    Yo tenia entendido que solo era la primera

    ReplyDelete
  5. claro, tipo visual basic, no solo texto o que resalte sintaxis solamente

    ReplyDelete
  6. el gedit tiene muchos agregados para resaltar sintaxis, esta muy bueno.

    ReplyDelete