Introduccion Ruby

31
Introducción a Ruby © GSyC 2009 2 Introducción Ruby es un lenguaje interpretado, orientado a objetos creado por Yukihiro Matsumoto (Matz), 1995. Última versión estable 1.9.1, 11/02/2009. Todos los tipos de datos son un objeto, incluidas las clases, tipos primitivos.

description

Introduccion Ruby

Transcript of Introduccion Ruby

Page 1: Introduccion Ruby

Introducción a Ruby

© GSyC 20092

Introducción

• Ruby es un lenguaje interpretado, orientado a objetos creado por Yukihiro Matsumoto (Matz), 1995.

• Última versión estable 1.9.1, 11/02/2009.

• Todos los tipos de datos son un objeto, incluidas las clases, tipos primitivos.

Page 2: Introduccion Ruby

© GSyC 20093

Primer programa

# Programa en ruby

puts'Hola Ruby'

x=1

puts(x)

El resultado de ejecutar este programa es:

hola Ruby1

Los comentarios comienzan por "#"Otra forma:=begin código comentado=end

Cada instrucción se escribe en una línea diferente, no es necesario ";"

No se define "main" o bloque principal

No es necesario declarar

variables antes de usarlas.

Declaración implícita de variables.

Se pueden omitir los paréntesis en las llamadas a funciones, si no hay ambigüedad

© GSyC 20094

Primer programa# Programa en rubydef hola(nombre) puts "hola #{nombre}"endhola('Ruby')x=1puts(x)

El resultado de ejecutar este programa es:

hola Ruby1

Declaración de una función

Invocación de la función hola

Sustitución de la variable

La comilla simple y las dobles

comillas tienen significado diferente

Page 3: Introduccion Ruby

© GSyC 20095

Ejecución de un programa en Ruby

• Ejecutar ruby cargando el fichero del programa.

~> ruby -w <filename>

• Ejecutar el intérprete interactivo (irb) e introducir sentencias por la entrada estándar.

~> irb >> 2+2 => 4

• Ejecutar un script de ruby~> ./miPrograma.rb

Muestra el valor de retorno de cada sentencia

Prompt de irb

© GSyC 20096

• Un script de ruby debe comenzar con una primera línea que indique dónde se encuentra el intérprete de ruby:

• El fichero debe ser ejecutable.• No es muy portable ya que depende del

directorio donde se haya instalado ruby.

Script de Ruby

#!/usr/bin/ruby -w#Programa en rubydef hola(nombre) puts "hola #{nombre}"endhola('Ruby')

Fichero miPrograma.rb

Page 4: Introduccion Ruby

© GSyC 20097

Ayuda ri• Referencia interactiva: herramienta que

muestra descripciones de los métodos, clases y módulos predefinidos en Ruby.

~> ri String.capitalize

------------------------------------------------------ String#capitalize

str.capitalize => new_str

------------------------------------------------------------------------

Returns a copy of _str_ with the first character converted to

uppercase and the remainder to lowercase.

"hello".capitalize #=> "Hello"

"HELLO".capitalize #=> "Hello"

"123ABC".capitalize #=> "123abc"

© GSyC 20098

def saludo(nombre)res = "Buenos días, #{nombre}"return res

end

puts saludo('Alicia')

def saludo(nombre) "Buenos días, #{nombre}"

end

puts saludo('Alicia')

Valor de retorno de una función

• El valor de retorno de una función es el valor de la última expresión ejecutada.

• Los siguientes ejemplos son equivalentes:

Page 5: Introduccion Ruby

© GSyC 20099

Asignaciones especiales

• En Ruby casi cualquier cosa devuelve un valor. Así, pueden encadenarse asignaciones:a = b = c = 4;

• Asignación paralela:a, b = b, a # intercambia a y b

• Existen las asignaciones con atajos de C:a += 2 # incrementa a en 2

(no existen los operadores ++ y --)

© GSyC 200910

Identificadores• Variables locales, nombres de métodos y parámetros

de métodos comienzan por letra minúscula o por _:– lista, n_maximo, num

• Variables globales comienzan por $:– $count, $1

• Variables de instancia comienzan por @:– @nombre, @edad, @n_dni

• Variables de clase comienzan por @@:– @@instancia, @@tabla

• Nombres de clases, módulos y constantes comienzan por letra mayúscula:– MiClase, String, Fixnum, – MAX_NUM, MIN_NUM

Page 6: Introduccion Ruby

© GSyC 200911

Ejercicio

• Ej1: Realiza un programa en Ruby que defina una función cuyo valor de retorno sea una cadena de caracteres similar a: – El producto de x por y es z

Donde x e y pueden ser valores cualesquiera que se le pasan a la función como parámetros y z=x*y. El programa calculará el producto de los números 5 y 6 e imprimirá la cadena de caracteres:"El producto de 5 por 6 es 30"

© GSyC 200912

Arrays

• Colección de referencias a objetos indexados por un entero. El índice del primer elemento es 0.– Literal:

a = [1, 'cat', 3.14] # a[0]=1; a[1]="cat"; a[2]=3.14a = ['uno', 'dos', 'tres'] # a[0]="uno"; a[1]="dos"; a[2]="tres"a = %w(uno dos tres) # %w: array de palabras

– Crear array y añadir elementos:a = Array.newa << 1 << 'cat' << 3.14 # a[0]=1; a[1]="cat"; a[2]=3.14

– Crear un array de cierto tamaño cuyas posiciones están incializadas como referencias a un cierto objeto.a = Array.new(10, 'aa') # a[0]="aa"; a[1]="aa"; … ; a[9]="aa"a[0]<< 'b' # a[0]="aab"; a[1]="aab"; … ; a[9]="aab"

Page 7: Introduccion Ruby

© GSyC 200913

Ejemplos con arrays

a = [3.14, "hola", 1] => [3.14, "hola", 1]a.class => Arraya.length => 3a[0] => 3.14a[1] => "hola"a[2] => 1a[3] => nila[-1] => 1b = [1, 3, 5, 7, 9] => [1, 3, 5, 7, 9]b[1..3] => [3, 5, 7]b[1...3] => [3, 5]b[3..3] => [7]b[-3..-1] => [5, 7, 9]

3.14 "hola" 1a=

Índices positivos -> 0 1 2

-3 -2 -1 <- Índices negativos

© GSyC 200914

Pilas y Colas con arrays

pila = Array.new()pila.push('a')pila.push('b')pila.push('c') # pila = ["a", "b", "c"]print pila.pop until pila.empty? # imprime cba

cola = Array.new()cola.push('a')cola.push('b')cola.push('c') # cola = ["a", "b", "c"]print cola.shift until cola.empty? # imprime abc

Page 8: Introduccion Ruby

© GSyC 200915

Array#join y String#split

["a", "b", "c"].join => "abc"["a", "b", "c"].join(" ") => "a b c"["a", "b", "c"].join("-") => "a-b-c"["a", "b", "c"].join("-*-") => "a-*-b-*-c"[1, 2, 3].join => "123"[1, 2, 3, "hola"].join => "123hola"

"hola a todos".split => ["hola", "a", "todos"]"12/11/2008".split("/") => ["12", "11", "2008"]

© GSyC 200916

Hash• Similar a un array, se puede utilizar cualquier

objeto como índice o clave.h = {'uno' => 1, 'dos' => 2, 'tres' => 3}puts h['uno'] # Imprime 1puts h['dos'] # Imprime 2puts h['tres'] # Imprime 3

• Los índices/claves de un hash deben ser únicos.– No puede haber dos valores diferentes para h['uno']

• Un hash devuelve nil cuando se utiliza un índice para el que no se ha definido un valor en ese hash.

• Un array es más eficiente que un hash, pero un hash permite mayor flexibilidad.

Page 9: Introduccion Ruby

© GSyC 200917

Ejecución condicional• IF

– if devuelve el valor de la última expresión ejecutada.– la palabra then solo es obligatoria si el if se escribe en una sola línea– la palabra then puede sustituirse (si se quiere) por el carácter :– Una condición es cierta si su evaluación es cualquier cosa salvo false o nil

(objeto que representa "nada").– El valor 0 no es false, es más, es true (¡sorpesa!)

• UNLESS: si no se cumple la condición…

if a<10 thenx= 'menor que 10'

elsif a>=10 and a<=20 thenx='entre 10 y 20'

else x='mayor que 20'

end

x = if a<10 then 'menor que 10'elsif a>=10 and a<=20 then 'entre 10 y 20'else 'mayor que 20'end

unless a<1 thenx='mayor o igual que 1'

else x='menor que 1'

end

© GSyC 200918

x='mayor o igual que 1' unless a<1

x='mayor o igual que 1' if a>=1

if y unless como modificadores

• La expresión anterior al modificador if es evaluada si la condición es cierta:

• La expresión anterior al modificador unless es evaluada si la condición es falsa:

Page 10: Introduccion Ruby

© GSyC 200919

Ejecución condicional con case

• CASE:– La condición se comprueba utilizando el operador === que tiene significado

diferente según el tipo de objeto que se use con case.• Para expresiones regulares: búsqueda de patrones

– La cláusula else: si no se cumple alguna de las condiciones anteriores.– Las cláusulas when pueden llevar o no al final then o : (como el if)

x = case iwhen 1, 2..5 then puts "menor que

6"when 6..10 then puts "mayor que

6" end

case strwhen 'aaa', 'bbb'

puts 'aaa or bbb'when /def/

puts "incluye /def/"

else puts "Cualquier

cosa"end

© GSyC 200920

Bucles

• WHILE UNTIL

• FOR: (en realidad es otra forma de escribir el iterador each)

• Modificadores:

while line = gets # …end

until not (line = gets) # …end

c = 2while c < 1000

c = c * cend

c = 2c = c *c while c < 1000

begin # …end while line = gets

for i in 1..10puts "#{i}"

end

for i in %w(a b c)puts "#{i}"

end

begin # …end until c<100

Page 11: Introduccion Ruby

© GSyC 200921

Expresiones regulares

• Forma de especificar un patrón de caracteres que se encuentra en una cadena: /patrón/

• Abreviaturas para clases de caracteres:\d cualquier carácter numérico del 0 al 9\D cualquier carácter excepto los numéricos del 0 al 9\s cualquier carácter "whitespace" (blanco, tabulador, fin de línea, fin de fichero\S cualquier carácter excepto los "whitespace"\w cualquier carácter propio de una palabra (letras y números, mayúsculas

minúsculas)\W cualquier carácter salvo los propios de una palabra

• Ejemplos:/Perl|Python/ # "Perl" o "Python"/P(erl|ython)/ # "Perl" o "Python"/\d\d:\d\d:\d\d/ # dd:dd:dd, ej: 12:23:45/Perl *Python/ # "Perl" 0 ó más espacios "Python"/Perl +Python/ # "Perl" 1 ó más espacios "Python"

© GSyC 200922

Expresiones regulares• Operador de búsqueda de una patrón: =~

– Busca un determinado patrón en una cadena de caracteres. Devuelve la posición donde lo encuentra o nil.

– Ejemplo, line es una cadena:if line =~ /Perl|Python/

puts "Lenguaje #{line}"end

• Extraer patrones:/(.*) (.*)/ =~ "hola ruby" => 0[$1, $2] => ["hola", "ruby"]

re = /nombre:"(.*)"/ => /nombre:"(.*)"/mr = re.match('nombre: "ruby"') => #<MatchData:0x402c1fc0>mr[1] => "ruby"

Page 12: Introduccion Ruby

© GSyC 200923

Expresiones regulares y sustituciones

• El patrón encontrado en una cadena de caracteres puede ser sustituido utilizando métodos de sustitución. Suponiendo que line contiene una cadena de caracteres:– Sustituye la primera vez que se encuentre 'Perl' en

la variable line por 'Ruby':line.sub(/Perl/, 'Ruby')

– Sustituye todas las apariciones de "Perl" en la variable line por 'Ruby':line.gsub(/Perl/, 'Ruby')

© GSyC 200924

Bloques• Un bloque es un conjunto de instrucciones que puede asociarse

a una llamada de un método, como si fuera un parámetro.• Un bloque se define entre llaves o entre las palabras reservadas

do…end.{ if x>0 then x else 0 } do

puts "hola"

puts "esto es un bloque"

end

• Para asociar un bloque a un método, el bloque se escribe a continuación de la llamada al método (después de los parámetros que hubiera que pasar al método).

• Dentro de un método se utiliza la instrucción yield para ejecutar el bloque asociado al método.

• Los bloques pueden tener sus propios argumentos, que se pasarán en el yield.

Cuando el resultado es importante

Cuando el efecto lateral es importante

Page 13: Introduccion Ruby

© GSyC 200925

Ejemplo de bloquedef llama_al_bloque puts "Comienza el método" yield yield puts "Fin del método"end

llama_al_bloque {puts "Bloque"}

def llama_al_bloque puts "Comienza el método" yield("hola",3) puts "Fin del método"end

llama_al_bloque {|str, num| puts "Bloque str=#{str} num=#{num}"}

Argumentos del bloque

Ejecuta el bloque asociado al método llama_al_bloque

Bloque asociado al método llama_al_bloque

Bloque asociado al método llama_al_bloque

Ejecuta el bloque asociado al método llama_al_bloquepasándole los argumentos

© GSyC 200926

Iteradores

• Métodos que devuelven sucesivamente elementos pertenecientes a una colección, por ejemplo, un array o un rango de números.

• En pseudocódigo, each estará implementado de la siguiente forma:

animales = %w(perro gato caballo)animales.each {| animal | puts animal }

# dentro de la clase Arraydef each for each element

yield(element)end

end

Variable local que toma el valor de cada elemento de una colección con cada iteración. for i in animales do

puts iend

Page 14: Introduccion Ruby

© GSyC 200927

['yo', 'soy', 'un', 'plátano'].each do |entry| print entry, ' ' end

Ejemplos de iteradores

• El resultado de un bloque puede utilizarlo el que llama a dicho bloque

(0..100).inject(0) { |result, entry| result + entry }=> 5050

fac=1 => 11.upto(5) do |i| fac*=i endfac => 120

result la primera vez vale 0 y las siguientes veces es el resultado de la ejecución del bloque. entry es el elemento i-ésimo de la colección en cada iteraciónSi se omite el argumento del inject, result la primera vez es el primer elemento de la colección, y se va iterando con los elementos a partir del segundo

[1, 2, 3, 4, 5].map {|entry| entry*entry } => [1, 4, 9, 16, 25]

Devuelve un nuevo array después de iterar sobre los elementos del array y ejecutar el bloque con cada uno de ellos.

© GSyC 200928

Más ejemplos

4.times do |i| puts i*=2 end

3.upto(6) {|i| print i }

('a'.. 'e').each {|char| print char }

a=%w(a b c) => ["a", "b", "c"]a.collect {|x| x.succ } => ["b", "c", "d"]a => ["a", "b", "c"]

a=%w(a b c) => ["a", "b", "c"]a.collect! {|x| x.upcase } => ["A", "B", "C"]a => ["A", "B", "C"]

(0..100).inject { |result, entry| result + entry }=> 5050

Iteración entre enteros desde 0 a n-1

Misma funcionalidad que map

Sin argumentos: la primera vez que se ejecuta el bloque, result toma el valor del primer elemento de la colección y entry el valor del segundo. En el mismo ejemplo donde se le pasa un valor por defecto a result, el bloque se ejecuta n veces. En este ejemplo el bloque se ejecuta n-1 veces

El ! Indica que se modifica la variable a con el resultado de ejecutar collect

Page 15: Introduccion Ruby

© GSyC 200929

Más ejemplos

def f(count, &block)value = 11.upto(count) do |i|

value = value *iblock.call(i, value)

endend

f 5 do |i, f_i| puts "f(#{i})= #{f_i}" end f(1) = 1

f(2) = 2

f(3) = 6

f(4) = 24

f(5) =120

Pasar un bloque como parámetro de una función

def f(count)value = 11.upto(count) do |i|

value = value *iyield(i, value)

endend

f(5) do |i, f_i| puts "f(#{i})= #{f_i}" end

Ejecuta el bloqueblock

© GSyC 200930

Ejercicios• Ej2: Escribe una función iterador n_times que llame a un

bloque n veces.def n_times(n) # …end

• Ej3: Utilizando inject de un rango de números escribe una función que calcule n!.def fac(n) # …end

• Ej4: Escribe una función que calcule la cadena más larga dentro de un array.def longest_string(array) # …end

La longitud de una cadena de caracteres puede saberse utilizando:

a="hola"a.length

Page 16: Introduccion Ruby

© GSyC 200931

Clases y Objetos• Los nombres de clases comienzan con la primera

letra en mayúscula.• El método new crea un nuevo objeto de una

determinada clase.s=String.new

• Todas las clases heredan de la clase Object.• En ruby todo son objetos y por tanto, pueden

invocarse sus métodos de la siguiente forma: objeto.metodo– Los hemos estado usando:

• line.gsub(…), 1.upto(3), x.upcase

• Ruby dispone de un recolector de basura que se encarga de destruir los objetos cuando ya no se usan.

© GSyC 200932

Ejemplos de objetos

(4.6).round => 5(4.6).class => Float(4.6).round.class => Fixnum-4.class => Fixnum

'hola'.length => 4'hola'.class => String'hola'.gsub('h', 'm') => "mola"

['esto', 'es', 'un', 'array'].length => 4

(4).+(3) => 7# En algunos casos, notación infija (azúcar sintáctico)4 + 3 => 7

Page 17: Introduccion Ruby

© GSyC 200933

Clases y objetos

• En algunos lenguajes de programación orientados a objetos:– Los objetos son datos– Las clases son tipos de datos

• En ruby las clases también son objetos de tipo Class:

10.class => FixNum"hola".class => StringFixnum.class => ClassString.class => ClassFloat.class => ClassClass.class => Class

© GSyC 200934

Las clases también son objetos

• Se pueden utilizar las clases como objetos:

• Se pueden invocar los métodos de las clases, como se invocan los métodos de los objetos:

if a then b=String else b=Array end

x= b.new # x puede ser un String o un Array dependiendo del valor de a

String.new => ""String.methods => ["inspect", "private_class_method",

"const_missing", "clone", "method", "public_methods", … ]

Page 18: Introduccion Ruby

© GSyC 200935

Definición de clases y declaración de objetos

class Persona @@numero_personas=0 def initialize(nombre, edad, viva=true)

@nombre = nombre@edad = edad@viva = viva@@numero_personas +=1

end

def saludo"Me llamo #{@nombre} y tengo #{@edad} años"

endend

alicia = Persona.new('Alicia', 20)puts alicia.saludo

Imprime en la salida estándar "Me llamo Alicia y tengo 20 años"

Definición de la clase Persona (primera letra con mayúscula)

Constructor

Variable alicia que es un nuevo objeto de la clase Persona. Se construye llamando a initialize de Persona

Las variables de instancia comienzan por @

Variables locales del método

Método de la clase Persona

Las variables de clase (atributos estáticos) comienzan por @@

Valor por defecto

© GSyC 200936

self• Dentro de un método de una clase self es una

referencia al objeto sobre el que dicho método se ha invocado.

• self puede utilizarse para invocar otros métodos, pero no para invocar atributos

• Muchas veces utilizar self es redundante.class Persona

...

def nuevo_saludo_1 "Saludo 1: " + saludo

end

def nuevo_saludo_2 "Saludo 2: " + self.saludo

end

end

Page 19: Introduccion Ruby

© GSyC 200937

Herencia

class Mujer < Persona def initialize (nombre, edad, n_partos, viva=true)

super(nombre, edad, viva)@n_partos = n_partos

endend

puts Mujer.new("Diana", 22, 0).saludo

m = Mujer.new("Marisa", 40, 1)m.inspect # devuelve el id del objeto

# y las variables de instancia

La clase Mujer hereda de la clase Persona. Es una especialización de Persona.

Se invoca dentro de un método para ejecutar el método del mismo nombre en la clase padre. En este caso se llama al constructor de Persona

Crea un objeto de tipo Mujer e imprime en la salida estándar "Me llamo Diana y tengo 22 años"

#<Mujer:0x24d74 @edad=40, @nombre="Marisa", @n_partos=1, @viva=true>

© GSyC 200938

Sobrecarga de métodos

• Ruby no permite la sobrecarga de métodos:– Una clase no puede tener dos métodos con

el mismo nombre y diferente número de parámetros. Si los tiene, sólo será válido el último que tenga definido.

– Sólo puede existir un constructor por clase.

Page 20: Introduccion Ruby

© GSyC 200939

Métodos de clase

• Funcionan sin necesidad de ser invocados a partir de una determinada instancia.– Método new: persona= Persona.new– Método para borrar un fichero: File.delete("nombre")

class Ejemplo def metodo_de_instancia end

def Ejemplo.metodo_de_clase endend

Definición de un método de clase class Ejemplo def self.metodo_de_clase end

class <<self def metodo_de_clase end endend

Otras formas de definir métodos de clase

© GSyC 200940

Objetos y atributos• Los atributos de una instancia del objeto Persona son privados y

sólo los métodos de una instancia tienen acceso a ellos.• Para que una instancia pueda mostrar el contenido de sus

atributos es necesario definir– Métodos que muestren el valor de los atributos

class Persona def initialize(nombre, edad, viva=true)

@nombre, @edad, @viva = nombre, edad, vivaenddef nombre @nombreenddef edad @edadenddef viva

@vivaend

end

class Personaattr_reader :nombre, :edad, :viva

def initialize(nombre, edad, viva=true) @nombre, @edad, @viva = nombre, edad, vivaend

end

Definiciones equivalentes

Page 21: Introduccion Ruby

© GSyC 200941

Objetos y atributos• Para que una instancia pueda modificar el contenido de sus

atributos desde fuera de los métodos de dicha instancia, es necesario definir– Métodos que modifiquen el valor de los atributos

class Persona def initialize(nombre, edad, viva=true)

@nombre, @edad, @viva = nombre, edad, vivaenddef edad=(nueva) @edad=nuevaend

end class Personaattr_writer :edad

def initialize(nombre, edad, viva=true) @nombre, @edad, @viva = nombre, edad, vivaend

end

Definiciones equivalentes

© GSyC 200942

Ejemploclass Persona

attr_writer :edadattr_reader :nombre, :edad, :viva

def initialize(nombre, edad, viva=true)@nombre, @edad, @viva = nombre, edad, viva

endend

p=Persona.new("daniel", 2)puts "El nombre es #{p.nombre}"p.edad +=1puts "#{p.nombre} tiene #{p.edad} años"

Page 22: Introduccion Ruby

© GSyC 200943

Objetos y atributos

• Crear funciones de lectura y modificación para los atributos de una clase:

class Personaattr_accessor :nombre, :edad, :viva

def initialize(nombre, edad, viva=true)@nombre, @edad, @viva = nombre, edad, viva

endend

© GSyC 200944

Símbolos• Es un objeto que puede ser representado por un número o por una

cadena de caracteres.– :abc es un objeto Symbol y se interpreta como "la cosa llamada abc"

• Sólo existe un único símbolo asociado a un determinado nombre.– Si en un código se hace referencia varias veces a :abc, se está

haciendo referencia siempre al mismo objeto.– Un símbolo NO es un String:

puts "hola".class => Stringputs :hola.class => Symbolputs "hola".object_id => 174582puts "hola".object_id => 170082puts :hola.object_id => 3913998puts :hola.object_id => 3913998

• Se utilizan para representar nombres y cadenas de caracteres. Los símbolos ahorran memoria y tiempo– Para crear una tabla hash:

• h= {:nombre => "Pepe", :email => "[email protected]"}

– Nombre de variable, método, constante.• attr_reader :nombre

Page 23: Introduccion Ruby

© GSyC 200945

Control de acceso• En Ruby la única forma de cambiar el estado de un

objeto es a través de sus métodos.• Controlando el acceso a los métodos, se controla el

acceso al estado del objeto.• Existen 3 niveles de protección:

– Métodos públicos: cualquiera puede llamarlos. Por defecto son todos públicos (salvo initialize)

– Métodos protegidos: sólo pueden llamarlos los objetos de la clase definida y sus subclases. El acceso queda controlado dentro de esa familia de objetos.

– Métodos privados: sólo los puede invocar el propio objeto. No se puede llamar a los métodos privados de otro objeto, incluso si el objeto que los llama es de la misma clase que el otro objeto. Por ello, sólo se permite invocar un método privado en la forma m(...) y no en la forma o.m(...), para ningún o (¡ni siquiera self!).

© GSyC 200946

Especificar el control de acceso

class MiClase def metodo1 # … end

protected def metodo2 # … end

private def metodo3 # … end

public def metodo4 # … end

end

class MiClase def metodo1 # … end def metodo2 # … end def metodo3 # … end def metodo4 # … end

public :metodo1, :metodo4 protected :metodo2 private :metodo3

end

Page 24: Introduccion Ruby

© GSyC 200947

Ejemploclass Persona

def nombre'Marisa'

end

def apellido'Lopez'

end

def nombre_completoconstruye_nombre

end

def construye_nombrenombre + " " + apellido

end

protected :nombre_completoprivate :construye_nombre

end

p = Persona.newputs p.nombreputs p.apellidoputs p.nombre_completoputs p.construye_nombre

© GSyC 200948

Ejemploclass Persona

def nombre'Marisa'

end

def apellido'Lopez'

end

protecteddef nombre_completo

construye_nombreend

privatedef construye_nombre

nombre + " " + apellidoend

end

class PersonaAccPublico < Personadef nombre_completo_publico

self.nombre_completoend

def construye_nombre_publico construye_nombreend

end

p = PersonaAccPublico.new

puts p.nombre_completo_publicoputs p.construye_nombre_publico

PersonaAccPublico tiene los mismos métodos de Persona porque los ha heredado. Permite que se ejecute nombre_completo a través del método público nombre_completo_publico. Permite que se ejecute construye_nombre a través del método público construye_nombre_publico.

Page 25: Introduccion Ruby

© GSyC 200949

Ejemploclass Persona

def nombre'Marisa'

end

def apellido'Lopez'

end

protecteddef nombre_completo

construye_nombreend

privatedef construye_nombre

nombre + " " + apellidoend

end

class PersonaAccPublico < Personadef nombre_completo_publico

self.nombre_completoend

def construye_nombre_publico self.construye_nombreend

end

p = PersonaAccPublico.new

puts p.nombre_completo_publicoputs p.construye_nombre_publico

Por ser un método privado, no puede invocarse sobre ningún objeto (¡ni siquiera self!).

© GSyC 200950

class Personadef nombre

'Marisa'end

def apellido'Lopez'

end

protecteddef nombre_completo

construye_nombreend

privatedef construye_nombre

nombre + " " + apellidoend

publicdef igual_a?(otro)

self.nombre_completo.eql?(otro.nombre_completo)end

end

p = Persona.new

p.igual_a?(Persona.new)

nombre_completo es un método protegido y por tanto puede ser llamado desde los objetos de la clase en la que está definido y de las clases hijas.

Ejemplo

Page 26: Introduccion Ruby

© GSyC 200951

class Datosdef initialize(arg1, *list)

puts "Arg1=#{arg1}" puts "Lista longitud=#{list.length}" puts list

endend

d1 = Datos.new("dato1")d2 = Datos.new("dato1", "dato2")d3 = Datos.new("dato1", "dato2", "dato3")

Número variable de argumentos

Indica número variable de argumentos y captura un conjunto de argumentos como un único parámetro de tipo Array

Arg1=dato1

Lista longitud=0

Arg1=dato1

Lista longitud=1

dato2

Arg1=dato1

Lista longitud=2

dato2

dato3

© GSyC 200952

Objetos y variables

• Una variable no es un objeto.• Una variable es una referencia a un

objeto.person1 = "Tim"person2 = person1person1[0]='J'

person1 => "Jim"person2 => "Jim"

"Tim"

String

person1 person2

Page 27: Introduccion Ruby

© GSyC 200953

El objeto nil

• El objeto nil es de la clase NilClass.• Ruby utiliza este valor para asignarlo a

los campos sin inicializar de una clase.

© GSyC 200954

Argumentos de la línea de comandos

• Los argumentos de la línea de comandos (después del nombre del programa) se guardan en un array de cadenas de caracteres en ARGV.– Para convertir un argumento a un número es necesario usar to_i:

• ARGV[0].to_i

– El nombre del programa se encuentra en la variable global $0

puts "Número de argumentos #{ARGV.length}"ARVG.each { |i| puts "Argumento #{i}" }puts "Nombre del programa #{$0}"

Page 28: Introduccion Ruby

© GSyC 200955

Excepciones

• Un código bien programado debe anticiparse a los errores, en Ruby, utilizando las excepciones.

• Ruby predefine una jerarquía de excepciones a partir de la clase Exception.

• El usuario puede lanzar una de las excepciones ya definidas en Ruby o crear las suyas propias.

• Si un usuario quiere definir sus propias excepciones, éstas deberían heredar de StandardError o alguna de sus clases hijas para que por defecto se capturen.

• Una excepción tiene asociado un mensaje (cadena de caracteres) y la traza de llamadas (backtrace).

© GSyC 200956

Capturar excepcionesbegin # las excepciones lanzadas por este código # serán capturadas por la siguiente instrucción rescue

# … # … # …

rescue ExceptionClassA, ExceptionClassB => e1 # se ejecuta si el código lanza una ExceptionClassA # o ExceptionClassB

# e1 toma el valor de la excepción que se ha lanzado rescue ExceptionClassC => e2 # se ejecuta si el código lanza una ExceptionClassC

# e2 toma el valor de la excepción que se ha lanzado rescue # captura una excepción StandardError ensure # código que siempre se ejecutaend

Page 29: Introduccion Ruby

© GSyC 200957

Lanzar excepcionesbegin

# … # … # …

raise # Relanza de nuevo la misma excepción (o RuntimeError si no

# se había lanzado hasta ahora ninguna excepción) raise "Servidor caído"

# Crea una excepción RuntimeError con el mensaje # "Servidor caído" y la lanza raise EServerDown, "El servidor no responde" # crea una excepción de tipo EServerDown y le asocia el # mensaje "El servidor no responde"end

© GSyC 200958

Del libro Pragmatic Bookshelf - Programming Ruby

Page 30: Introduccion Ruby

© GSyC 200959

Algunas excepciones habituales

Del libro Ruby for Rails

© GSyC 200960

Ejemploclass MiExcepcion < Exception; end

class MiExcepcionHija < MiExcepcion; end

class MiOtraExcepcionHija < MiExcepcion; end

def pruebaExcepciones

begin

puts "Prueba a lanzar MiOtraExcepcionHija"

raise MiOtraExcepcionHija

puts "no deberia imprimirse"

rescue MiExcepcionHija

puts "Capturada mi excepcion hija"

raise

rescue MiOtraExcepcionHija

puts "Capturada mi otra excepcion hija"

raise

end

end

begin

pruebaExcepciones

rescue MiExcepcion => e

puts "#{e} ha ocurrido"

puts "Por favor, contacta con el administrador del sistema :)"

end

Page 31: Introduccion Ruby

© GSyC 200961

Incluir ficheros

• Es frecuente ver una organización del código Ruby en diferentes ficheros, por ejemplo dividiendo las clases definidas en ficheros distintos.

• Para poder usar las clases definidas en otros ficheros, es necesario utiliza la instrucción require.

require 'nombreFichero'

• Las variables locales no se propagan al ámbito desde donde se invoca require.

© GSyC 200962

Ejemplo: require

a=1def b 2end

Fichero f1.rba="gato"require 'f1'

puts aputs b

Fichero f2.rb

Escribe:gato2

Las variables locales no se propagan con require.