Capítulo 12. Métodos

¿Qué es un método? En la programación OO no se piensa en operar sobre los datos directamente desde el exterior de un objeto; si no que los objetos tienen algún conocimiento de cómo se debe operar sobre ellos (cuando se les pide amablemente). Podríamos decir que se pasa un mensaje al objeto y este mensaje obtienen algún tipo de acción o respuesta significativa. Esto debe ocurrir sin que tengamos necesariamente algún tipo de conocimiento o nos importe como realiza el objeto, interiormente, el trabajo. Las tareas que podemos pedir que un objeto realice (o lo que es lo mismo, los mensajes que comprende) son los métodos.

En Ruby, se llama a un método con la notación punto (como en C++ o Java). El objeto con el que nos comunicamos se nombra a la izquierda del punto.

  ruby> "abcdef".length
  6
  

Intuitivamente, a este objeto cadena se le está pidiendo que diga la longitud que tiene. Técnicamente, se está llamando al método length del objeto "abcdef".

Otros objetos pueden hacer una interpretación un poco diferente de length. La decisión sobre cómo responder a un mensaje se hace al vuelo, durante la ejecución del programa, y la acción a tomar puede cambiar dependiendo de la variable a que se haga referencia.

  ruby> foo = "abc"
  "abc"
  ruby> foo.length
  3
  ruby> foo = ["abcde","fghij"]
  ["abcde", "fghij"]
  ruby> foo.length
  2
  

Lo que indicamos con length puede variar dependiendo del objeto con el que nos comunicamos. En el primer ejemplo le pedimos a foo su longitud, como referencia a una cadena simple, sólo hay una respuesta posible. En el segundo ejemplo, foo referencia a un array, podríamos pensar que su longitud es 2, 5 ó 10; pero la respuesta más plausible es 2 (los otros tipos de longitud se podrían obtener si se desea)

  ruby> foo[0].length
  5
  ruby> foo[0].length + foo[1].length
  10
  

Lo que hay que tener en cuenta es que, el array conoce lo que significa ser un array. En Ruby, las piezas de datos llevan consigo ese conocimiento por lo que las solicitudes que se les hace se pueden satisfacer en las diferentes formas adecuadas. Esto libera al programador de la carga de memorizar una gran cantidad de nombres de funciones, ya que una cantidad relativamente pequeña de nombre de métodos, que corresponden a conceptos que sabemos como expresar en lenguaje natural, se pueden aplicar a diferentes tipos de datos siendo el resultado el que se espera. Esta característica de los lenguajes OO (que, IMHO[1], Java ha hecho un pobre trabajo en explotar), se conoce como polimorfismo

Cuando un objeto recibe un mensaje que no conoce, "salta" un error:

  ruby> foo = 5
  5
  ruby> foo.length
  ERR: (eval):1: undefined method `length' for 5:Fixnum
  

Por lo tanto hay que conocer qué métodos son aceptable para un objeto, aunque no se necesita saber como son procesados.

Si se pasan argumentos a un método, éstos van normalmente entre paréntesis.

  objeto.metodo(arg1, arg2)
  

pero se pueden omitir, si su ausencia no provoca ambigüedad

  objeto.metodo arg1, arg2
  

En Ruby existe una variable especial self que referencia al objeto que llama a un método. Ocurre con tanta frecuencia que por conveniencia se omite en las llamadas de un método dentro de un objeto a sus propios métodos:

  self.nombre_de_metodo(args ...)
  

es igual que:

  nombre_de_metodo(args ...)
  

Lo que conocemos tradicionalmente como llamadas a funciones es esta forma abreviada de llamar a un método a través de self. Esto hace que a Ruby se le conozca como un lenguaje orientado a objetos puro. Aún así, los métodos funcionales se comportan de una forma muy parecida a las funciones de otros lenguajes de programación en beneficio de aquellos que no asimilen que las llamadas a funciones son realmente llamadas a métodos en Ruby. Se puede hablar de funciones como si no fuesen realmente métodos de objetos, si queremos.

Notas

[1]

In My Honest Opinion (En mi honesta opinión)