35 - Objetos: colaboración

Normalmente un problema de mediana complejidad resuelto con la metodología de programación orientada a objetos no interviene una sola clase, sino que hay muchas clases que interactúan y se comunican.

Plantearemos un problema separando las actividades en dos clases.

Problema 1:

Un banco tiene 3 clientes que pueden hacer depósitos y extracciones. También el banco requiere que al final del día calcule la cantidad de dinero que hay depositado.

Lo primero que hacemos es identificar las clases:

Podemos identificar la clase Cliente y la clase Banco.

Luego debemos definir los atributos y los métodos de cada clase:

Cliente		
    atributos
        nombre
        monto
    métodos
        initialize
        depositar
        extraer

Banco
    atributos
        3 Cliente (3 objetos de la clase Cliente)
    métodos
        initialize
        operar
        depositos_totales

Programa: ejercicio144.rb

class Cliente

  attr_reader :monto

  def initialize(nombre)
    @nombre = nombre
    @monto = 0
  end

  def depositar(monto)
    @monto = @monto + monto
  end

  def extraer(monto)
    @monto = @monto - monto
  end
 
  def imprimir
    puts "#{@nombre} tiene depositado la suma de #{@monto}"
  end
end


class Banco

  def initialize
    @cliente1 = Cliente.new "Juan"
    @cliente2 = Cliente.new "Ana"
    @cliente3 = Cliente.new "Diego"
  end

  def operar
    @cliente1.depositar 100
    @cliente2.depositar 150
    @cliente3.depositar 200
    @cliente3.extraer 150
  end

  def depositos_totales
    total = @cliente1.monto + @cliente2.monto + @cliente3.monto
    puts "El total de dinero del banco es: #{total}"
    @cliente1.imprimir
    @cliente2.imprimir
    @cliente3.imprimir
  end
end

# bloque principal        

banco1=Banco.new
banco1.operar
banco1.depositos_totales

Primero hacemos la declaración de la clase Cliente, en el método inicializate cargamos los atributos @nombre con el valor que llega como parámetro y el atributo @monto con el valor cero:

class Cliente

  attr_reader :monto

  def initialize(nombre)
    @nombre = nombre
    @monto = 0
  end

Para poder acceder desde otra clase al atributo @monto llamamos a attr_reader:

  attr_reader :monto

El método que aumenta el atributo @monto es:

  def depositar(monto)
    @monto = @monto + monto
  end

Y el método que reduce el atributo @monto del cliente es:

  def extraer(monto)
    @monto = @monto - monto
  end

Para mostras los datos del cliente tenemos el método:

  def imprimir
    puts "#{@nombre} tiene depositado la suma de #{@monto}"
  end

La segunda clase de nuestro problema es el Banco. Esta clase define tres atributos de la clase Cliente (la clase Cliente colabora con la clase Banco):

class Banco

  def initialize
    @cliente1 = Cliente.new "Juan"
    @cliente2 = Cliente.new "Ana"
    @cliente3 = Cliente.new "Diego"
  end

El método operar realiza una serie de depósitos y extracciones de los clientes:

  def operar
    @cliente1.depositar 100
    @cliente2.depositar 150
    @cliente3.depositar 200
    @cliente3.extraer 150
  end

El método que muestra cuanto dinero tiene depositado el banco se resuelve pidiendo a cada cliente que retorne el monto que tiene (recordemos que podemos acceder al atributo @monto del cliente gracias a que definimos en la otra clase attr_reader :monto):

  def depositos_totales
    total = @cliente1.monto + @cliente2.monto + @cliente3.monto
    puts "El total de dinero del banco es: #{total}"
    @cliente1.imprimir
    @cliente2.imprimir
    @cliente3.imprimir
  end

Problema 2:

Plantear un programa que permita jugar a los dados. Las reglas de juego son:
se tiran tres dados si los tres salen con el mismo valor mostrar un mensaje que "gano", sino "perdió".

Lo primero que hacemos es identificar las clases:

Podemos identificar la clase Dado y la clase JuegoDeDados.

Luego los atributos y los métodos de cada clase:

Dado		
    atributos
        valor
    métodos
        initialize
        tirar
        imprimir

JuegoDeDados
    atributos
        3 Dado (3 objetos de la clase Dado)
    métodos
        initialize
        jugar

Programa: ejercicio145.rb

class Dado

  attr_reader :valor

  def initialize
    @valor = 1
  end

  def tirar
    @valor = 1 + rand(6)
  end

  def imprimir
    puts "Valor del dado: #{@valor}"
  end
end


class JuegoDeDados

  def initialize
    @dado1 = Dado.new
    @dado2 = Dado.new
    @dado3 = Dado.new    
  end
  
  def jugar
    @dado1.tirar
    @dado1.imprimir
    @dado2.tirar
    @dado2.imprimir
    @dado3.tirar
    @dado3.imprimir
    if @dado1.valor == @dado2.valor &&
       @dado1.valor == @dado3.valor
      puts "Gano"
    else
      puts "Perdio"
    end
  end  
end

# bloque principal del programa

juego_dados = JuegoDeDados.new
juego_dados.jugar

La clase Dado define un método tirar que almacena en el atributo valor un número aleatorio comprendido entre 1 y 6:

  def tirar
    @valor = 1 + rand(6)
  end

Llamamos al método attr_reader pasando el atributo valor para tener acceso desde fuera de la clase al número que se generó

  attr_reader :valor

La clase JuegoDeDados define tres atributos de la clase Dado, en el método initialize donde se crean dichos objetos:

class JuegoDeDados

  def initialize
    @dado1 = Dado.new
    @dado2 = Dado.new
    @dado3 = Dado.new    
  end

En el método jugar de la clase JuegoDeDados procedemos a pedir a cada dado que se tire, imprima y verificamos si los tres valores son iguales:

  def jugar
    @dado1.tirar
    @dado1.imprimir
    @dado2.tirar
    @dado2.imprimir
    @dado3.tirar
    @dado3.imprimir
    if @dado1.valor == @dado2.valor &&
       @dado1.valor == @dado3.valor
      puts "Gano"
    else
      puts "Perdio"
    end
  end  

En el bloque principal de nuestro programa creamos un objeto de la clase JuegoDeDados:

# bloque principal del programa

juego_dados = JuegoDeDados.new
juego_dados.jugar

Problema propuesto

  • Plantear una clase Club y otra clase Socio.
    La clase Socio debe tener los siguientes atributos: nombre y la antigüedad en el club (en años).
    En el método initialize de la clase Socio pedir la carga por teclado del nombre y su antigüedad.
    La clase Club debe tener como atributos 3 objetos de la clase Socio.
    Definir una responsabilidad para imprimir el nombre del socio con mayor antigüedad en el club.
Solución
ejercicio146.rb

class Socio
  attr_reader :antiguedad

  def initialize
    print "Ingrese el nombre del socio:"
    @nombre = gets.chomp
    print "Ingrese la antiguedad:"
    @antiguedad = gets.to_i
  end

  def imprimir
    puts "#{@nombre} tiene una antiguedad de #{@antiguedad}"
  end
end


class Club

  def initialize
    @socio1 = Socio.new
    @socio2 = Socio.new
    @socio3 = Socio.new
  end

  def mayor_antiguedad
    puts "Socio con mayor antiguedad"
    if @socio1.antiguedad > @socio2.antiguedad &&
       @socio1.antiguedad > @socio3.antiguedad
      @socio1.imprimir
    elsif @socio2.antiguedad > @socio3.antiguedad
      @socio2.imprimir
    else
      @socio3.imprimir
    end
  end
end     

# bloque principal

club = Club.new
club.mayor_antiguedad