En Ruby, todo lo que se manipula es un objeto, y el resultado de esas operaciones también son objetos. La única forma que tenemos de manipular los objetos, son los métodos:
5.times { puts "Ratón!\n" } #se hablará más tarde de bloques
"A los elefantes le gustan los cacahuetes".length
Si los objetos (como los strings, números,…) son los nombres, entonces los métodos son los verbos. Todo método necesita un objeto. Es fácil decir qué objeto recibe el método: el que está a la izquierda del punto. Algunas veces, puede que no sea obvio. Por ejemplo, cuando se usa puts
y gets
, ¿dónde están sus objetos? Nada más iniciarse el intérprete, estamos dentro de un objeto: el objeto main
. Por tanto, al usar puts y gets, estamos mandando el mensaje al objeto main
.
¿Cómo podemos saber dentro de qué objeto estamos? Usando la variable self
.
puts self
Un bloque de instrucciones que define un método, empieza por la palabra def y acaba por la end. Los parámetros son la lista de variables que van entre paréntesis. Aunque en Ruby, dichos paréntesis son opcionales: puts
, p
y gets
son muy usados, y por ello que el uso de paréntesis sea opcional. En Rails, se llama a los métodos sin paréntesis.
Un método devuelve el valor de su última línea. Por norma, es recomendable dejar una línea en blanco entre las definiciones de métodos:
#metodos.rb
# Definición de un método
def hello
puts 'Hola'
end
#uso del método
hello
# Método con un argumento
def hello1(nombre)
puts 'Hola ' + nombre
return 'correcto'
end
puts(hello1('Pedro'))
# Método con un argumento (sin paréntesis, no funciona en versiones nuevas)
def hello2 nombre2
puts 'Hola ' + nombre2
return 'correcto'
end
puts(hello2 'Juan')
Esto es lo que obtenemos
>ruby metodos.rb
Hola
Hola Pedro
correcto
Hola Juan
correcto
metodos.rb:18 warning: parenthesize argument(s) for future version
>Exit code: 0
Los métodos que acaban con una !
son métodos que modifican al objeto. Por lo tanto, estos métodos son considerados como peligrosos, y existen métodos iguales, pero sin el !
. Por su peligrosidad, el nombre "bang". Ejemplo:
a = "En una lugar de la mancha"
#método sin bang: el objeto no se modifica
b = a.upcase
puts b
puts a
#método con bang: el objeto se modifica
c = a.upcase!
puts c
puts a
Normalmente, por cada método con !
, existe el mismo método sin !
. Aquellos sin bang, nos dan el mismo resultado, pero sin modificar el objeto (en este caso el string). Las versiones con !
, como se dijo, hacen la misma acción, pero en lugar de crear un nuevo objeto, transforman el objeto original.
Ejemplos de esto son: upcase
/ upcase!
, chomp
/chomp!
,…En cada caso, si haces uso de la versión sin !
, tienes un nuevo objeto. Si llamas el método con !
, haces los cambios en el mismo objeto al que mandaste el mensaje.
alias nuevo_nombre nombre_original
alias crea un nuevo nombre que se refiere a un método existente. Cuando a un método se le pone un alias, el nuevo nombre se refiere al método original: si el método se cambia, el nuevo nombre seguirá invocando el original.
def viejo_metodo
"viejo metodo"
end
alias nuevo_metodo viejo_metodo
def viejo_metodo
"viejo metodo mejorado"
end
puts viejo_metodo
puts nuevo_metodo
En el resultado, vemos como nuevo_metodo
hace referencia al viejo_metodo
sin modficar:
viejo metodo mejorado
viejo metodo
Cuando mandas un mensaje a un objeto, el objeto busca en su lista de métodos, y ejecuta el primer método con el mismo nombre del mensaje que encuentre. Si no encuetra dicho método, lanza una error NoMethodError
.
Una forma de solucionar esto, es mediante el método method_missing
: si definimos dicho método dentro de una clase, se ejecuta este método por defecto:
class Dummy
def method_missing(m, *args)
puts "No existe un metodo llamado #{m}"
end
end
Dummy.new.cualquier_cosa
obtenemos:
No existe un metodo llamado cualquier_cosa
Por lo tanto, method_missing
es como una red de seguridad: te da una forma de manejar aquellos métodos que de otra forma darían un error en tu programa.
Ruby deja especificar los valores por defecto de los argumentos, que son usados si no se especifica un valor explícitamente. Se hace esto mediante el operador de asignación =
:
#argumentos.rb
def mtd(arg1="Dibya", arg2="Shashank", arg3="Shashank")
"#{arg1}, #{arg2}, #{arg3}."
end
puts mtd
puts mtd("ruby")
Hemos usado el operador interpolación #{ }
: se calcula la expresión entre paréntesis, y el resultado se añade al string. Lo que obtenemos es:
>ruby argumentos.rb
Dibya, Shashank, Shashank.
ruby, Shashank, Shashank.
>Exit code: 0
Ruby permite escribir funciones que acepten un número variable de argumentos. Por ejemplo:
def foo(*mi_string)
mi_string.each do |palabras|
puts palabras
end
end
foo('hola', 'mundo')
foo()
El asterisco indica que el número de argumentos puede ser el que se quiera. En este ejemplo, el asterisco toma los argumentos y los asigna a un array (o vector de elementos) llamado mi_string
. Haciendo uso de ese asterisco, incluso se pueden pasar cero argumentos; que es lo que pasa con foo()
.
No hay máximo número de argumentos que podamos pasar a un método.
Si se quieren incluir argumentos opcionales, tienen que venir después de los argumentos no opcionales:
def arg_opc(a,b,*x) # bien
def arg_opc(a,*x,b) # mal
Los argumentos se interpretan de izquierda a derecha, por eso es importante que los argumentos no opcionales vayan en primer lugar. Si los pusiésemos en último lugar, no sabríamos decir donde acaban los argumentos opcionales y donde empiezan los no opcionales.
=begin
Ejemplo de como los argumentos se
interpretan de izquierda a derecha
=end
def mtd(a=99, b=a+1)
[a,b]
end
puts mtd
Lecciones atrás vimos el método puts
que saca datos por la pantalla. ¿Cómo podemos introducir nuestros propios datos? Para esto gets (get=coger, s=string) y chomp son de ayuda. Veamos el siguiente ejemplo:
# gets y chomp
puts "¿En qué ciudad te gustaría vivir?"
STDOUT.flush
ciudad = gets.chomp
puts "La ciudad es " + ciudad
El ejemplo superior, al ser ejecutado en SciTe, clickea en la pantalla de output y pon el nombre de tu ciudad favorita. STDOUT
es una constante global que almacena las salidas del programa. flush vacía cualquier dato almacenado, y por lo tanto, limpiará cualquier resultado anterior. chomp
es un método para strings y gets
almacena strings que provienen del teclado. El problema es que gets almacena lo escrito y el caráter \n
(retorno de carro); chomp
lo que hace es borrar el carácter: \n
.
RAILS: los datos vienen de muchos sitios. En la típica aplicación de Rails, vienen de una base de datos. Como un desarrollador de Rails, puedes usar con frecuencia algunos de estos métodos, porque Rails recoge los datos que los usuarios escriben en los formularios Web.
Escribe un programa que pregunte por la temperatura en grados Fahrenheit. El programa usará este dato, y hallará el equivalente en grados Celsius. El resultado final lo mostrará en pantalla con dos decimales. (Celsius (°C) = [ Fahrenheit (°F) - 32 ] / 1.8)
Nota: para formatear un resultado a dos decimales, hay dos opciones:
format
. Por ejemplo:x = 45.5678
puts format("%.2f", x)
round
:puts (x*100).round/100.0