Machetazo Ruby

Descargar como txt, pdf o txt
Descargar como txt, pdf o txt
Está en la página 1de 23

Pepita == Norita

retorna false
Norita == Pepita
retorna false
Norita == Norita
retorna true
"hola" == "chau"
retorna false
***************************************************
Se le envia un mensaje:
Pepita.cantar!
=> "pri pri pri"

****************************************************
Mensajes definidos para Pepita
Pepita.energia
=> 100
Pepita.comer_lombriz!
=> nil
Pepita.volar_en_circulos!
=> nil

**************************************************
Como vimos, un objeto puede entender múltiples mensajes; a este conjunto de
mensajes que podemos enviarle lo denominamos interfaz. Por ejemplo, la interfaz de
Pepita es:

energia: nos dice cuanta energía tiene (un número);


cantar!: hace que cante;
comer_lombriz!: hace que coma una lombriz;
volar_en_circulos!: hace que vuele en circulos.
Lo cual también se puede graficar de la siguiente forma:
*************************************************************
Como convención, a los mensajes con efecto (es decir, que hacen algo) les pondremos
un signo de exclamación ! al final.
**************************************************************
Esto significa que dos o más objetos pueden entender un mismo mensaje, pero pueden
comportarse de formas diferentes. Ya hablaremos más de esto en próximas lecciones.
********************************************************************
Pepita.comer_alpiste! 40
Allí, 40 es un argumento del mensaje, representa en este caso que vamos a alimentar
a pepita con 40 gramos de alpiste. Un mensaje podría tomar más de un argumento,
separados por coma.
**********************************************************************
Pepita.comer_alpiste! 500
Pepita.volar_hacia! Iruya
Pepita.volar_hacia! Obera
***************************************************************
Es fácil ver que en Pepita.volar_hacia! Barreal el objeto receptor es Pepita, el
mensaje volar_hacia! y el argumento Barreal; pero ¿dónde queda eso de objeto y
mensaje cuando hacemos, por ejemplo, 2 + 3?

Como ya dijimos, todas nuestras interacciones en un ambiente de objetos ocurren


enviando mensajes y las operaciones aritméticas no son la excepción a esta regla.

En el caso de 2 + 3 podemos hacer el mismo análisis:

el objeto receptor es 2;
el mensaje es +;
el argumento es 3.

5.+ 6
Retorna 11
3.< 27
Retorna true
Pepita.== Norita
Retorna False
************************************************************
En un mundo de objetos, todo lo que tenemos son objetos y mensajes. A estos
últimos, podemos distinguirlos según la forma en que se escriben:

Mensajes de palabra clave. Su nombre está compuesto por una o varias palabras,
puede terminar con un signo de exclamación ! o de pregunta ?, y se envía mediante
un punto. Además,

pueden no tomar argumentos, como Rayuela.anio_de_edicion;


o pueden tomar uno o más argumentos, separados por coma: SanMartin.cruzar!
LosAndes, Mula.
Operadores. Son todos aquellos cuyo "nombre" se compone de uno o más símbolos, y
se envían simplemente escribiendo dichos símbolos. En cuanto a los argumentos,

pueden no tomar ninguno, como la negación !true;


o pueden tomar uno (y solo uno), como Orson == Garfield o energia + 80.
Como vimos, también se pueden escribir como mensajes de palabra clave (aunque no
parece buena idea escribir 1.== 2 en vez de 1 == 2 ).
************************************************************************

argumentos
Pepita.comer_alpiste! 90
Pepita.volar_hacia! Iruya
Pepita.comer_alpiste! (Pepita.energia*0.1)
*************************************************************
Definicion de objeto

module Pepita
end
******************************************************************

module Pepita
def self.cantar!
end
end
Un método es, entonces, la descripción de qué hacer cuando se recibe un mensaje del
mismo nombre.

Dos cosas muy importantes a tener en cuenta :

Todos los métodos comienzan con def y terminan con end. Si nos falta alguna de
estos dos la computadora no va a entender nuestra solución.
Todos los métodos que pertenezcan al mismo objeto van dentro del mismo module.
********************************************************************
Definiendo el efecto de los mensajes

module Pepita
@energia = 100

def self.volar_en_circulos!
@energia -= 10
end
end
*****************************************************************
Los metodos solo devuelven una cosa pero pueden tener varios efectos

def self.comprar_libro!
@plata -= 300
@libros += 1
end
********************************************************************
Los parametros pueden tener nombre propio
module Pepita
@energia = 100
@ciudad=Iruya
def self.volar_en_circulos!
@energia -= 10
end
def self.comer_lombriz!
@energia += 20
end
def self.volar_hacia! lugar
@energia -=100
@ciudad=lugar
end
# Seguí por acá...
end
***************************************************************
Los atributos no son mensajes
module Pepita
#...atributos y métodos anteriores...

def energia
@energia
end
end
******************************************************
estado_pepita = %w(
energia
ciudad
)

estado_kiano1100 = %w(
)

estado_rolamotoC115 = %w(
)

estado_enrique = %w(
celular
dinero_en_billetera
frase_favorita
)

****************************************************
Mensaje de valor absoluto
17.abs
=> 17

(-17).abs
=> 17

(1710 - 1040).abs
=> 670

(1040 - 1710).abs
=> 670

(1040 - 1710).abs / 2
=> 335
***************************************************************
usar metodos en otros metodos

module Obera
def self.kilometro
1040
end
end

module Iruya
def self.kilometro
1710
end
end

module BuenosAires
def self.kilometro
0
end
end
module Pepita
@energia = 1000
@ciudad = Obera

def self.energia
@energia
end

def self.ciudad
@ciudad
end

def self.cantar!
'pri pri pri'
end

def self.comer_lombriz!
@energia += 20
end

def self.volar_en_circulos!
@energia -= 10
end

def self.volar_hacia!(destino)
@energia -= (destino.kilometro - ciudad.kilometro).abs/2
@ciudad = destino
end
end
*********************************************************************
Self distancia

module Pepita
@energia = 1000
@ciudad = Obera

def self.energia
@energia
end

def self.ciudad
@ciudad
end

def self.cantar!
'pri pri pri'
end

def self.comer_lombriz!
@energia += 20
end

def self.volar_en_circulos!
@energia -= 10
end

def self.volar_hacia!(destino)
self.gastar_energia!(destino)
@ciudad = destino
end

def self.gastar_energia!(destino)
@energia -= (self.distancia_a (destino) )/ 2
end
def self.distancia_a (city)
(@ciudad.kilometro-city.kilometro).abs
end
end
***************************************************************
Comunicacion entre modulos

module Obera
def self.kilometro
1040
end
def self.distancia_a (city)
(self.kilometro-city.kilometro).abs
end

end

module Iruya
def self.kilometro
1710
end
def self.distancia_a (city)
(self.kilometro-city.kilometro).abs
end
end

module BuenosAires
def self.kilometro
0
end
def self.distancia_a (city)
(self.kilometro-city.kilometro).abs
end
end

module Pepita
@energia = 1000
@ciudad = Obera

def self.energia
@energia
end

def self.ciudad
@ciudad
end

def self.cantar!
'pri pri pri'
end

def self.comer_lombriz!
@energia += 20
end

def self.volar_en_circulos!
@energia -= 10
end

def self.volar_hacia!(destino)
self.gastar_energia!(destino)
@ciudad = destino
end
def self.gastar_energia!(destino)
@energia -= (@ciudad.distancia_a (destino) )/ 2
end

end
*****************************************************************
En Ruby, es una convención que los mensajes que devuelven booleanos (o sea,
verdadero o falso) terminen con un ?.
********************************************************************
module Jose
def self.acomodar_habitacion!
self.ordenar!
if self.tiene_sabanas_sucias?
self.cambiar_sabanas!
end
self.tender_la_cama!
end
end
***************************************************************
module Jardinero
def self.cuidar!(planta)
if planta.necesita_agua?
3.times { self.regar! planta }
else
self.sacar_bichos! planta
end
end
end

*************************************************************************
module Pepita
@energia = 1000

def self.energia
@energia
end

def self.volar_en_circulos!
@energia -= 10
end

def self.comer_alpiste!(gramos)
@energia += gramos * 15
end

def self.debil?
@energia<100
end

def self.feliz?
@energia>1000
end
def self.hacer_lo_que_quiera!
if self.debil?
self.comer_alpiste! 10
else
3.times {self.volar_en_circulos!}
end
end
end
*******************************************************************
NO olvidar las llaves

module Pepita
@energia = 1000

def self.energia
@energia
end

def self.volar_en_circulos!
@energia -= 10
end

def self.comer_alpiste!(gramos)
@energia += gramos * 15
end
def self.debil?
@energia<100
end

def self.feliz?
@energia>1000
end
def self.hacer_lo_que_quiera!
if self.debil?
self.comer_alpiste! 10
else
if self.feliz?
5.times {self.volar_en_circulos!}
else
3.times {self.volar_en_circulos!}
end
end
end
end
*************************************************************************
module Pepo
2
@energia=1000
3
def self.energia
4
@energia
5
end
6
def self.comer_alpiste!(gramos)
7
@energia+= (gramos/2)
8
end
9
def self.pesado?
10
@energia>1100
11
end
12

13
def self.volar_en_circulos!
14
if self.pesado?
15
@energia-=15
16
else
17
@energia-=5
18
end
19
end
20
def self.hacer_lo_que_quiera!
21
self.comer_alpiste! 120
22
end
23
end
************************************************************************
Enviar ordenes a otro modulo

module Pachorra
def self.entrenar_ave!
10.times {Pepita.volar_en_circulos!}
Pepita.comer_alpiste! 30
5.times {Pepita.volar_en_circulos!}
Pepita.hacer_lo_que_quiera!
end
end
*******************************************************************
Antes de empezar a entrenar, debe firmar un contrato con el ave. Esto, por ejemplo,
lo haríamos de la siguiente manera:

Pachorra.firmar_contrato! Pepita # ahora el ave de Pachorra es Pepita

Pachorra.entrenar_ave! # acá entrena a Pepita


Pachorra.firmar_contrato! Pepo # ahora el ave de Pachorra es Pepo
Pachorra.entrenar_ave! # ahora entrena a Pepo

********************************************************************
usar nombre de parametros adentro del metodo
module Pachorra

def self.firmar_contrato! (pajaro)


@ave=pajaro
end
def self.entrenar_ave!

10.times {@ave.volar_en_circulos!}
@ave.comer_alpiste! 30
5.times {@ave.volar_en_circulos!}
@ave.hacer_lo_que_quiera!
end
end
************************************************************
Para probar en consola solo debo llamar

Emilce.firmar_contrato! Pepo

Emilce.entrenar_ave!

************************************************

Según las rutinas que definen, cada entrenador/a solo puede trabajar con ciertas
aves:

Pachorra puede entrenar a cualquier ave que entienda volar_en_circulos!,


comer_alpiste!(gramos) y hacer_lo_que_quiera!.
Emilce puede entrenar a cualquier ave que entienda volar_en_circulos! y
comer_alpiste!(gramos).
Dicho de otra manera, la rutina nos define cuál debe ser la interfaz que debe
respetar un objeto para poder ser utilizado.
*******************************************************************
¿Qué pasa si dos objetos, como Pepita, Norita o Pepo son capaces de responder a un
mismo mensaje? Podemos intercambiar un objeto por otro sin notar la diferencia,
como experimentaste recién.
Este concepto es fundamental en objetos, y lo conocemos como polimorfismo. Decimos
entonces que dos objetos son polimórficos cuando pueden responder a un mismo
conjunto de mensajes y hay un tercer objeto que los usa indistintamente.
****************************************************************
Aunque parezca que no tiene mucho sentido, es común que trabajando con objetos
necesitemos forzar el polimorfismo y hagamos cosas como estas.

En este caso le agregamos a Norita un mensaje que no hace nada, con el único
objetivo de que sea polimórfica con sus compañeras aves.
*****************************************************************

module Pachorra

def self.ave=(ave_nueva)
@ave = ave_nueva
end

def self.entrenar_ave!
10.times { @ave.volar_en_circulos! }
@ave.comer_alpiste! 30
5.times { @ave.volar_en_circulos! }
@ave.hacer_lo_que_quiera!
end
end
***********************************************************************
Setters y Getters

Como ya te habíamos contado en una lección anterior, a estos métodos que solo
sirven para acceder o modificar un atributo los llamamos métodos de acceso o
accessors. Repasando, los setters son aquellos métodos que establecen el valor del
atributo. Mientras que los getters son aquellos que devuelven el valor del
atributo.

La convención en Ruby para estos métodos es:

Los setters deben llevar el mismo nombre del atributo al que están asociados,
agregando un = al final.
Los getters usan exactamente el mismo nombre que el atributo del cual devuelven el
valor pero sin el @.
Aquellos getters que devuelven el valor de un atributo booleano llevan ? al final.

*************************************************************************
module Inodoro
@cafeina_en_sangre = 90

def self.cafeina_en_sangre
@cafeina_en_sangre
end

def self.compinche=(nuevocompinche)
@compinche=nuevocompinche
end
def self.compinche
@compinche
end
end
module Eulogia
@enojada = false
def self.enojada?
@enojada
end
end

module Mendieta
@ganas_de_hablar = 5

def self.ganas_de_hablar
@ganas_de_hablar
end
def self.ganas_de_hablar=(nuevasganas)
@ganas_de_hablar=nuevasganas
end
end
*********************************************************************
En esta lección le dimos nombre al polimorfismo una idea con la que ya venías
trabajando, pero sobre la que todavía no habíamos reflexionado. Este principio
fundamental del paradigma de objetos nos permite que podamos interactuar de igual
manera con diferentes objetos, con el único requisito de que todos ellos entiendan
el o los mensajes que necesitamos enviarles.

Relacionado a esto, hablamos del encapsulamiento que nos permite el paradigma,


haciendo que cada objeto solo exponga lo necesario para interactuar con él y se
reserve para su ámbito privado lo que no sea necesario compartir.

En el caso de los atributos, esta exposición se logra implementando un getter


(método que nos permite ver su valor) o un setter (método que nos permite modificar
su valor). Y que nuestro código sea entendido fácilmente por otras personas,
elegimos utilizar una convención para darle nombre a estos métodos.
************************************************************************

saludo = "hola"
saludo.upcase
=> "HOLA"
************************************************************************
saludo = "hola"
...lo que estamos haciendo es crear una referencia saludo que apunta al objeto
"hola", que representamos mediante una flechita:
Y cuando tenemos...

saludo.upcase

...le estamos enviando el mensaje upcase al objeto "hola", a través de la


referencia saludo, que es una variable.
******************************************************

despedida="adiós"
despedida.size()

tambien sirve
"adiós".size()
4.abs.even?

el even es iguales creo


***************************************************
otro_saludo="buen día"
=> "buen día"
despedida=otro_saludo
=> "buen día"

otro_saludo = "buen día" # se crea la variable otro_saludo que referencia al objeto


"buen día"
despedida = otro_saludo # se crea la variable despedida que, por asignarle la
referencia otro_saludo, apunta al mismo objeto

"buen día".equal? "buen día"


=> false
despedida.equal? "buen día"
=> false

En ambos casos el resultado fue false, dado que aquellos strings son objetos
distintos, a pesar de que tengan los mismos caracteres. Cada vez que escribimos un
string estamos creando un nuevo objeto. Sin embargo:
otro_saludo.equal? otro_saludo

=> true
despedida.equal? otro_saludo
=> true

¿Por qué? ¡Simple! Ambas referencias, otro_saludo y despedida, apuntan al mismo


objeto. La moraleja es que declarar una variable significa agregar una nueva
referencia al objeto existente, en lugar de copiarlo:

******************************************************
Ya entendimos que dos strings con el mismo contenido no necesariamente son el mismo
objeto. Pero esto puede ser poco práctico . ¿Cómo hacemos si realmente queremos
saber si dos objetos, pese a no ser el mismo, tienen el mismo estado?
**********************************************************************
"hola" == "hola"
=> true
"hola" == "adiós"
=> false
"hola".equal? "hola"
=> false

El mensaje == nos permite comparar dos objetos por equivalencia; lo cual se da


típicamente cuando los objetos tienen el mismo estado. Y como vemos, puede devolver
true, aún cuando los dos objetos no sean el mismo.

**********************************************************************

¡Ojo! A diferencia de la identidad, que todos los objetos la entienden sin tener
que hacer nada especial, la equivalencia es un poco más complicada.

Por defecto, si bien todos los objetos también la entienden, delega en la


identidad, así que muchas veces es lo mismo enviar uno u otro mensaje
Y para que realmente compare a los objetos por su estado, vos tenés que implementar
este método a mano en cada objeto que crees. Los siguientes objetos ya la
implementan:
Listas
Números
Strings
Booleanos

*********************************************************************

Hay tres referencias a este objeto:

La propia referencia Iruya


El atributo @ciudad de Pepita
una_ciudad: porque los parámetros de los métodos ¡también son referencias! Sólo que
su vida es más corta: viven lo que dure la evaluación del método en el que se
pasan.
**********************************************************************

#Ya definimos a Pepita por vos.


#Ahora definí su ciudad...
Pepita.ciudad=Iruya

**************************************************************
¡Exacto! Si bien:

Pepita e Iruya son objetos bien conocidos;


@energiay @ciudad son atributos;
y una_ciudad es un parámetro;
¡Todas son referencias!

**********************************************************
Fito.amigo = Juli
AbueloGervasio.nieto = Juli

#Si antes de alimentar al nieto preguntáramos Fito.es_feliz_como_su_amigo?,


respondería false

3.times { AbueloGervasio.alimentar_nieto! }

...Juli es un objeto compartido: tanto el abuelo como su amigo lo conocen. La


consecuencia de esto es que cuando su abuelo le da de comer le aumenta la
felicidad, y su amigo ve los cambios: éste método que antes devolvía false, ahora
devuelve true.

Y esto tiene sentido: si un objeto muta su estado, y lo expone de una u otra forma
a través de mensajes, todos los que lo observen podrán ver el cambio.

****************************************************************
Ejemplo de relacion entre objetos y TADS

module Fideos
@ajies = 0
def self.ajies
@ajies
end
def self.agregar_ajies!(cantidad)
@ajies+=cantidad
end
def self.quitar_ajies! (cantidad)
@ajies-=cantidad
end
def self.descartar_la_salsa!
@ajies = 0
end
def self.picantes?
@ajies>2
end
end

module Jor
def self.plato_del_dia
@platodia
end
def self.plato_del_dia=(plato)
@platodia=plato
end
def self.picantear!
@platodia.agregar_ajies!(5)
end
end
module Luchi
def self.suavizar! (platodeldia,quitar)
if platodeldia.ajies>10
platodeldia.descartar_la_salsa!
else
platodeldia.quitar_ajies!(quitar)
end
end
end

*************************************************************
module CarlosDuty
@cantidad_logros=0
def self.dificultad
30-@cantidad_logros*0.5
end
def self.violento?
TRUE
end
def self.jugar!(un_tiempo)
if un_tiempo>2
@cantidad_logros+=1
end
end
end

module TimbaElLeon

@dificultad=25
def self.violento?
FALSE
end
def self.jugar!(un_tiempo)
@dificultad+=un_tiempo
end
def self.dificultad
@dificultad
end

end
module Metroide
@nivel_espacial=3

def self.violento?
if @nivel_espacial>5
TRUE
end
end
def self.jugar!(un_tiempo)
@nivel_espacial+=1
end
def self.dificultad
100
end

end
*****************************************************************
Veamos si se entiende: definí un objeto Juegoteca que tenga un atributo juegos con
su correspondiente getter. La Juegoteca tiene que tener en primer lugar el juego
CarlosDuty, luego TimbaElLeon y por último Metroide.

module Juegoteca
@juegos=[CarlosDuty,TimbaElLeon,Metroide]
def self.juegos
@juegos
end
end
*****************************************************************
Operaciones con listas push y delete
numeros_de_la_suerte = [6, 7, 42]
numeros_de_la_suerte.push 9
# Agrega el 9 a la lista...
numeros_de_la_suerte.delete 7
# ...y quita el 7.
************************************************************
También podemos saber saber si un elemento está en la colección usando include?:
numeros_de_la_suerte.include? 6
# Devuelve true, porque contiene al 6...
numeros_de_la_suerte.include? 8
# ...devuelve false, porque no contiene al 8.
*********************************************************************
Finalmente, podemos saber la cantidad de elementos que tiene enviando size:
numeros_de_la_suerte.size
# Devuelve 3, porque contiene al 6, 42 y 9

**************************************************************
numeros_de_la_suerte = [6, 7, 42]
numeros_de_la_suerte.first
# Nos retorna el primer elemento de la lista
numeros_de_la_suerte.last
# Nos retorna el último de la lista
numeros_de_la_suerte.index 7
# Nos retorna la posición de un elemento en la lista

*********************************************************************
Otro tipo muy común de colecciones son los sets (conjuntos), los cuales tienen
algunas diferencias con las listas:

no admiten elementos repetidos;


sus elementos no tienen un orden determinado.
Vamos a ver un ejemplo transforma una lista en un set utilizando to_set:
numeros_aleatorios = [1,27,8,7,8,27,87,1]
numeros_aleatorios
=> [1,27,8,7,8,27,87,1]
numeros_aleatorios.to_set
=> #<Set: {1, 27, 8, 7, 87}>
*******************************************************************
Cuidado con ! para negar todo o solo una parte usar parentesis
module Juegoteca
@puntos=0
@juegos=[CarlosDuty,TimbaElLeon,Metroide]
def self.juegos
@juegos
end
def self.puntos
@puntos
end
def self.adquirir_juego!(un_juego)
juegos.push un_juego
@puntos+=150
end
def self.borrar_juego!(un_juego)
juegos.delete un_juego
end
def self.completa?
@puntos>1000 && juegos.size>5
end
def self.juego_recomendable? (un_juego)
!(juegos.include?un_juego) && un_juego.violento?
end
end

***********************************************************
Con call se ejecuta, sin call queda sin ejecutarse

Los bloques son objetos que representan un mensaje o una secuencia de envíos de
mensajes, sin ejecutar, lista para ser evaluada cuando corresponda. La palabra con
la que se definen los bloques en Ruby es proc. Por ejemplo, en este caso le
asignamos un bloque a incrementador:

un_numero = 7
incrementador = proc { un_numero = un_numero + 1 }
Ahora avancemos un pasito: en este segundo ejemplo, al bloque { otro_numero =
otro_numero * 2 } le enviamos el mensaje call, que le indica que evalúe la
secuencia de envíos de mensajes dentro de él.

otro_numero = 5
duplicador = proc { otro_numero = otro_numero * 2 }.call
*************************************************************

Los bloques también pueden recibir argumentos para su aplicación. Por ejemplo,
sumar_a_otros_dos recibe dos argumentos, escritos entre barras verticales | y
separados por comas:

un_numero = 3
sumar_a_otros_dos = proc { |un_sumando, otro_sumando| un_numero = un_numero +
un_sumando + otro_sumando }
Para aplicar el bloque sumar_a_otros_dos, se le pasan los argumentos deseados al
mensaje call:

sumar_a_otros_dos.call(1,2)
=> 6

****************************************************************
jugar_a_timba = proc{| un_tiempo| TimbaElLeon.jugar!(un_tiempo/60) }

************************************************************
¿Qué pasa cuando queremos todos aquellos objetos que cumplan con una condición
determinada en una cierta colección? Por ejemplo, si de una lista de números
queremos los mayores a 3.

Lo que usamos es el mensaje select de las colecciones. select recibe un bloque con
un parámetro que representa un elemento de la colección y una condición booleana
como código, y lo que devuelve es una nueva colección con los elementos que la
cumplen.

algunos_numeros = [1, 2, 3, 4, 5]
mayores_a_3 = algunos_numeros.select { |un_numero| un_numero > 3 }
¿Y cuándo se aplica ese bloque que recibe el select? ¡El select es quien decide!
La colección va a aplicarlo con cada uno de los objetos (un_numero) cuando
corresponda durante el seleccionado (o filtrado) de elementos.

mayores_a_3
=> [4, 5]

****************************************************************
module Juegoteca

@juegos=[CarlosDuty,TimbaElLeon,Metroide]
def self.juegos
@juegos
end
def self.juegos_violentos
juegos_violentos=juegos.select{|juego| juego.violento?}
end
end
**********************************************************
¿Y si en vez de todos los elementos que cumplan una condición, sólo queremos uno?
¡Usamos find!

algunos_numeros = [1, 2, 3, 4, 5]
uno_mayor_a_3 = algunos_numeros.find { |un_numero| un_numero > 3 }
Mientras que select devuelve una colección, find devuelve únicamente un elemento.

uno_mayor_a_3
=> 4
¿Y si ningún elemento de la colección cumple la condición? Devuelve nil, que, como
aprendiste antes, es un objeto que representa la nada - o en este caso, que ninguno
cumple la condición.
***********************************************************
Es lo mismo repitiendo el nombre de la variable o no
module Juegoteca
@juegos=[CarlosDuty,TimbaElLeon,Metroide]
def self.juegos
@juegos
end
def self.juego_mas_dificil_que(una_dificultad)
juego_mas_dificil_que=@juegos.find{|juego|juego.dificultad>una_dificultad}
end
end
*******************************************************
Para saber si todos los elementos de una colección cumplen un cierto criterio
podemos usar el mensaje all?, que también recibe un bloque. Por ejemplo, si tenemos
una colección de estudiantes, podemos saber si todo el grupo aprueba de la
siguiente forma:

estudiantes.all? { |un_estudiante| un_estudiante.aprobo? }


De manera muy similar podemos saber si algún elemento de la colección cumple cierta
condición mediante el mensaje any?. Siguiendo el ejemplo anterior, ahora queremos
saber si por lo menos alguien aprobó :

estudiantes.any? { |un_estudiante| un_estudiante.aprobo? }

*********************************************************
El mensaje map nos permite, a partir de una colección, obtener otra colección con
cada uno de los resultados que retorna un envío de mensaje a cada elemento.

En otras palabras, la nueva colección tendrá lo que devuelve el mensaje que se le


envíe a cada uno de los elementos. Por ejemplo, si usamos map para saber los
niveles de energía de una colección de golondrinas:

[Pepita, Norita].map { |una_golondrina| una_golondrina.energia }


=> [77, 52]
Al igual que el resto de los mensajes que vimos hasta ahora, map no modifica la
colección original ni sus elementos, sino que devuelve una nueva colección.

***************************************************************
Volviendo a nuestra colección de estudiantes. Ya preguntamos si todo el grupo
aprobó o si al menos alguien aprobó utilizando all?y any?. ¿Y si queremos saber
cuántos aprobaron? Usamos count:

estudiantes.count { |un_estudiante| un_estudiante.aprobo? }


count nos dice cuántos elementos de una colección cumplen la condición. Por otro
lado, para calcular sumatorias tenemos el mensaje sum. Si queremos conocer la suma
de todas las notas de la colección de estuidantes, por ejemplo, podemos hacer:

estudiantes.sum { |un_estudiante| un_estudiante.nota_en_examen }


****************************************************************

Hasta ahora, todos los mensajes que vimos de colecciones (con la excepción de push
y delete) no están pensados para producir efectos sobre el sistema. ¿Qué ocurre,
entonces, cuando queremos hacer algo con cada elemento? A diferencia del map, no
nos interesan los resultados de enviar el mismo mensaje a cada objeto, sino
mandarle un mensaje a cada uno con la intención de producir un efecto.

Es en este caso que nos resulta de utilidad el mensaje each.

Por ejemplo, si queremos que de una colección de golondrinas, aquellas con energía
mayor a 100 vuelen a Iruya, podríamos combinar select y each para hacer:

golondrinas
.select { |una_golondrina| una_golondrina.energia > 100 }
.each { |una_golondrina| una_golondrina.volar_hacia! Iruya }
**************************************************************
CLASES
class Zombi
def initialize
@salud = 100
end

def gritar
"¡agrrrg!"
end
def salud
@salud
end
def sabe_correr?
FALSE
end
def recibir_danio!(
puntos)
@salud=[(@salud-=(2*puntos)),0].max
end
def sin_vida?
@salud==0
end

end
*****************************************************************
Como habrás visto, definir una clase es muy similar a definir un objeto. Tiene
métodos, atributos... ¿cuál es su particularidad, entonces? La clase es un objeto
que nos sirve como molde para crear nuevos objetos.

Momento, ¿cómo es eso? ¿Una clase puede crear nuevos objetos?

¡Así es! Aprovechemos la clase Celular para instanciar los celulares de María y
Lucrecia:

celular_de_maría = Celular.new
celular_de_lucrecia = Celular.new
Celular, al igual que todas las clases, entiende el mensaje new, que crea una nueva
instancia de esa clase.
*****************************************************************
Como viste recién, la salud no se comparte entre bouba y kiki a pesar de que ambos
sean instancias de Zombi.

Pero nos quedó un método misterioso por aclarar: initialize. Al trabajar con clases
tenemos que inicializar los atributos en algún lugar. ¡Para eso es que existe ese
método!

El mensaje initialize nos permite especificar cómo queremos que se inicialice la


instancia de una clase. ¡Es así de fácil!

****************************************************************
Veamos si se entiende: Agregale veinte nuevos zombis a la colección caminantes. ¡No
olvides que los números entienden el mensaje times!

Luego, agregale un método ataque_masivo! a Sobreviviente, que reciba una colección


de zombis y los ataque a todos con 15 puntos de daño.

class Sobreviviente

def initialize
@energia=1000
end

def energia
@energia
end
def atacar!(zombie,
puntos)
zombie.recibir_danio!(puntos)
end
def ataque_masivo!(caminantes)
caminantes.each{|caminante| atacar!(caminante,15)}
end
end
juliana = Sobreviviente.new
anastasia = Sobreviviente.new

caminantes = []
20.times{ caminantes.push (Zombi.new)}

*******************************************************

class Celular
def initialize
@bateria=100
end
def utilizar!(minutos)
@bateria=@bateria-(minutos)/2
end

def cargar_a_tope!
@bateria=100
end
end

*****************************************************
SuperClase

El símbolo < significa "hereda de": por ejemplo, Condor hereda de Ave, que está más
arriba en la jerarquía. Otra manera de decirlo es que cada Condor es una Ave.

La herencia nos permite que las subclases (Condor y Halcon) posean los mismos
métodos y atributos que la superclase Ave. Es decir, las instancias de Condor y de
Halcon van a saber volar! de la misma forma, pero cuando les enviemos el mensaje
dormir! cada una hará algo diferente.

***********************************************************

Sabiendo que contamos con las clases Celular y Notebook, ¿alguna vez instanciaremos
un objeto de la clase Dispositivo? ¡Probablemente no! ¿Por qué querríamos crear
algo tan genérico si podemos crear algo más específico?

A este tipo de clases, como Dispositivo o Ave en el ejemplo del ejercicio anterior,
se las llama clases abstractas porque, a diferencia de las clases concretas (como
Celular o Notebook), nunca las instanciamos. En otras palabras, no creamos objetos
con esa clase, solo nos sirven para proveer comportamiento a sus subclases.

***********************************************************
class MedioDeTransporte
def initialize(litros)
@combustible=(litros)
end

def cargar_combustible!(litros)
@combustible+=litros
end

def entran?(cant)
self.maximo_personas >= (cant)
end
end

class Moto<MedioDeTransporte
def recorrer!(km)
@combustible=@combustible-(km)
end
def maximo_personas
2
end
end

class Auto<MedioDeTransporte
def maximo_personas
5
end
def recorrer!(km)
@combustible=@combustible-(km)/2
end
end

***********************************************************
.

También podría gustarte

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy