Programación | Aprendiendo Ruby 0003.1
Sufriendo con POO
El paradigma de POO (Programación Orientada a Objetos) siempre ha sido un problema para mí, debido la instrucción desordenada que recibí y que yo he continuado en programación. En la escuela aprendí a moverme con soltura en PHP pero siempre desde el paradigma procedimental, declarando y guardando variables... pero el POO solo lo vi de manera abstracta (mejor dicho conceptual; exposiciones de clase) lo que siempre ha sido para mi un reto, porque en programación se aprende practicando.
En internet también encontrar material para ejercitarse como el que yo requería es difícil. Los ejemplos siempre son muy ¿Simples? ¿No aplicables? Soy un cabeza dura, lo reconozco, aprendo a base de equivocarme una y otra vez. Así que se me ocurrió que ya que estoy aprendiendo Ruby, resolver los problemas clásicos de programación pero siguiendo en la medida que pueda los lineamientos de POO.
¿Que haremos hoy?
Sistemita que devuelve cambio
Un usuario ingresa una cantidad en el prompt y el programa se encarga de devolverle esa cantidad en billetes y monedas de distintas denominaciones
Le tengo cariño a este ejercicio porque fue el primer ejercicio donde en verdad me entretuve mentalmente en la escuela y no en mi casa con libros de la biblioteca.
Planteomoslo en paradigma POO
NOTA No tengo formación académica que me respalde, todo lo que hago es lo que creo que es y luego a base de golpes y metidas de pata me voy corrigiendo, así que no duda de mi, lector anónimo.
En POO debemos pensar primero en crear un molde genérico del programa, del que después iremos creando objetos específicos.
*Ese molde se llama CLASE*
class DarEfectivo
# Aquí todo el código del molde
end
En Ruby, siempre que se crea un objeto nuevo, busca un método llamado initialize y lo ejecuta.
initialize vendría siendo lo que en otros lenguajes conocen como constructor citando a Wikipedia:
En Programación Orientada a Objetos (POO), un constructor es una subrutina cuya misión es inicializar un objeto de una clase. En el constructor se asignan los valores iniciales del nuevo objeto.
Entonces, hagamos nuestro constructor, en este caso las variables que inicializaré serán dos arrays donde estarán almacenados las denominaciones de billetes y monedas.
Repito, fue la forma en que yo resolví el ejercicio y la forma en la que, de momento, he entendido el concepto.
Quedaría de esta forma:
class DarEfectivo
def initialize
@billetes =[1000,500,200,100,50,20]
@monedas = [10,5,2,1]
end
end
¡Ya tenemos nuestro molde! Pero aun está incompleto. debemos darle métodos.
Yo lo entendí de esta forma:
Un objeto tiene atributos y métodos. los atributos son como sus características, los métodos, en cambio, son las acciones que el objeto puede realizar.
En este caso, ¿Que acciones debe realizar nuestra clase para poder ayudarle al usuario con su cambio?
- recibir datos del usuario.
- devolver esos datos en billetes y monedas de distinta denominacion.
Por tanto, esos serán los dos métodos que crearemos:
Método 1: recibir datos del usuario
class DarEfectivo
#constructor
def initialize
@billetes =[1000,500,200,100,50,20]
@monedas = [10,5,2,1]
end
# recibir datos del usuario
def cantidad
print "Dame un cantidad: "
gets.chomp.to_i
end
end
Método 2: Devolver el resultado
Esta parte ya es mas familiar para mí ^^' y es que debemos resolver el ejercicio en sí. Le dí un par de vueltas (En la prepa lo resolvimos a bese de puro if y else anidado pues era el tema de la clase) y se me ocurrió usar each do que usamos con los números primos (NOTA MENTAL: convertir el programita de numeros primos a POO)
Lo que vamos a hacer es:
- Recorrer el array elemento por elemento (Comenzando con los de mayor denominación)
- Si la cantidad que ingresó el usuario es mayor o igual a la denominación del billete (elemento del array):
- obtener la cantidad de billetes de esa denominación que pueden acompletar la cantidad (una división entera)
- Si el resultado de esa división entera es mayor que uno, se imprimirá el texto “billetes de” (mas de un billete), de lo contrario se imprimirá el texto “billete de” (para ser mas agradable y natural al usuario)
- La variable cantidad se actualiza al resultado de la división modular entre el billete con el que se le aplicó la división entera. Es decir, obtener el sobrante, el cual se reutilizará con el siguiente elemento del array.
- Si la cantidad no es mayor o igual al elemento del array en el que se encuentre, se pasa al siguiente elemento.
- Cuando termine el array de @billetes, nos seguimos con el array de @monedas, que tendrá exactamente el mismo comportamiento que el anterior array.
Quizá en código se entienda mejor mi soliloquio ^^'
class DarEfectivo
# Constructor
def initialize
@billetes =[1000,500,200,100,50,20]
@monedas = [10,5,2,1]
end
# Recibir datos del usuario
def cantidad
print "Dame un cantidad: "
gets.chomp.to_i
end
# Devolver la cantidad en billetes y monedas de distinta denominación.
def cambio(cantidad)
@billetes.each do |billete|
if cantidad >= billete
print "#{cantidad.div(billete)} "
unless cantidad.div(billete) != 1 then puts "billete de #{billete}" else puts "billetes de #{billete}" end
cantidad=cantidad % billete
end
end
@monedas.each do |moneda|
if cantidad >= moneda
print "#{cantidad.div(moneda)} "
unless cantidad.div(moneda) != 1 then puts "moneda de #{moneda}" else puts "monedas de #{moneda}" end
end
end
end
end
Podemos notar algo interesante a diferencia del anterior método, y es que en def cantidad no pasamos ningún parámetro, a diferencia de def cambio(cantidad). Esto de pasar parámetros significa que hay métodos que necesitan un parámetro externo para trabajar.
Ahora sí, hemos terminado nuestro molde. Hora de crear un objeto para que nuestro usuario interactué con él.
# Creamos un objeto llamado mi_efectivo, a partir de la clase DarEfectivo.new
mi_efectivo = DarEfectivo.new
# La variable cantidad_ingresada guardará el valor que el usuario escriba en el método cantidad, que mandamos a llamar desde nuestro objeto creado.
cantidad_ingresada = mi_efectivo.cantidad
# ejecutamos el método cambio pasándole el valor de la variable cantidad_ingresada
mi_efectivo.cambio(cantidad_ingresada)
y ¡voila! nuestro programa funciona.