- Colaboración de clases


Normalmente un problema 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 depositada.

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
        constructor
        depositar
        extraer
        retornarMonto

Banco
    atributos
        3 Cliente (3 objetos de la clase Cliente)
        1 Scanner (Para poder hacer la entrada de datos por teclado)
    métodos
        constructor
        operar
        depositosTotales

Creamos un proyecto en Eclipse llamado: Proyecto1 y dentro del proyecto creamos dos clases llamadas: Cliente y Banco.

Programa:

public class Cliente {
    private String nombre;
    private int monto;
    
    public Cliente(String nom) {
        nombre=nom;
        monto=0;
    }
    
    public void depositar(int m) {
        monto=monto+m;
    }
    
    public void extraer(int m) {
        monto=monto-m;
    }
    
    public int retornarMonto() {
        return monto;
    }
    
    public void imprimir() {
        System.out.println(nombre+" tiene depositado la suma de "+monto);
    }
}





public class Banco {
    private Cliente cliente1,cliente2,cliente3;
	
    public Banco() {
        cliente1=new Cliente("Juan");
        cliente2=new Cliente("Ana");
        cliente3=new Cliente("Pedro"); 
    }

    public void operar() {
        cliente1.depositar (100);
        cliente2.depositar (150);
        cliente3.depositar (200);
        cliente3.extraer (150);
    }
	
    public void depositosTotales ()
    {
        int t = cliente1.retornarMonto () + cliente2.retornarMonto () + cliente3.retornarMonto ();
        System.out.println ("El total de dinero en el banco es:" + t);
        cliente1.imprimir();
        cliente2.imprimir();
        cliente3.imprimir();
    }

    public static void main(String[] ar) {
        Banco banco1=new Banco();
        banco1.operar();
        banco1.depositosTotales();
    }
}

Analicemos la implementación del problema.

Los atributos de una clase normalmente son privados para que no se tenga acceso directamente desde otra clase, los atributos son modificados por los métodos de la misma clase:

    private String nombre;
    private int monto;

El constructor recibe como parámetro el nombre del cliente y lo almacena en el atributo respectivo e inicializa el atributo monto en cero:

    public Cliente(String nom) {
        nombre=nom;
        monto=0;
    }

Los métodos depositar y extraer actualizan el atributo monto con el dinero que llega como parámetro (para simplificar el problema no hemos validado que cuando se extrae dinero el atributo monto quede con un valor negativo):

    public void depositar(int m) {
        monto=monto+m;
    }
    
    public void extraer(int m) {
        monto=monto-m;
    }

El método retornarMonto tiene por objetivo comunicar al Banco la cantidad de dinero que tiene el cliente (recordemos que como el atributo monto es privado de la clase, debemos tener un método que lo retorne):

    public int retornarMonto() {
        return monto;
    }

Por último el método imprimir muestra nombre y el monto de dinero del cliente:

    public void imprimir() {
        System.out.println(nombre+" tiene depositado la suma de "+monto);
    }

Como podemos observar la clase Cliente no tiene función main. Entonces donde definimos objetos de la clase Cliente?
La respuesta a esta pregunta es que en la clase Banco definimos tres objetos de la clase Cliente.

Veamos ahora la clase Banco que requiere la colaboración de la clase Cliente.
Primero definimos tres atributos de tipo Cliente:


public class Banco {
    private Cliente cliente1,cliente2,cliente3;

En le constructor creamos los tres objetos (cada vez que creamos un objeto de la clase Cliente debemos pasar a su constructor el nombre del cliente, recordemos que su monto de depósito se inicializa con cero):

    public Banco() {
        cliente1=new Cliente("Juan");
        cliente2=new Cliente("Ana");
        cliente3=new Cliente("Pedro"); 
    }

El método operar del banco (llamamos a los métodos depositar y extraer de los clientes):

    public void operar() {
        cliente1.depositar (100);
        cliente2.depositar (150);
        cliente3.depositar (200);
        cliente3.extraer (150);
    }

El método depositosTotales obtiene el monto depositado de cada uno de los tres clientes, procede a mostrarlos y llama al método imprimir de cada cliente para poder mostrar el nombre y depósito:

    public void depositosTotales ()
    {
        int t = cliente1.retornarMonto () + cliente2.retornarMonto () + cliente3.retornarMonto ();
        System.out.println ("El total de dinero en el banco es:" + t);
        cliente1.imprimir();
        cliente2.imprimir();
        cliente3.imprimir();
    }

Por último en la main definimos un objeto de la clase Banco (la clase Banco es la clase principal en nuestro problema):

    public static void main(String[] ar) {
        Banco banco1=new Banco();
        banco1.operar();
        banco1.depositosTotales();
    }

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
        tirar
        imprimir
        retornarValor

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

Creamos un proyecto en Eclipse llamado: Proyecto2 y dentro del proyecto creamos dos clases llamadas: Dado y JuegoDeDados.

Programa:

public class Dado {
    private int valor;
    
    public void tirar() {
        valor=1+(int)(Math.random()*6);
    }
    
    public void imprimir() {
        System.out.println("El valor del dado es:"+valor);
    }
    
    public int retornarValor() {
        return valor;
    }
}




public class JuegoDeDados {
    private Dado dado1,dado2,dado3;
    
    public JuegoDeDados() {
        dado1=new Dado();
        dado2=new Dado();
        dado3=new Dado();        	
    }
    
    public void jugar() {
        dado1.tirar();
        dado1.imprimir();
        dado2.tirar();
        dado2.imprimir();
        dado3.tirar();
        dado3.imprimir();
        if (dado1.retornarValor()==dado2.retornarValor() && 
            dado1.retornarValor()==dado3.retornarValor()) {
            System.out.println("Ganó");
        } else {
            System.out.println("Perdió");
        }        	
    }
    
    public static void main(String[] ar){
        JuegoDeDados j=new JuegoDeDados();
        j.jugar();
    }
}

La clase dado define el atributo "valor" donde almacenamos un valor aleatorio que representa el número que sale al tirarlo.

public class Dado {
    private int valor;

El método tirar almacena el valor aleatorio (para generar un valor aleatorio utilizamos el método random de la clase Math, el mismo genera un valor real comprendido entre 0 y 1, pero nunca 0 o 1. Puede ser un valor tan pequeño como 0.0001 o tan grando como 0.9999. Luego este valor generado multiplicado por 6 y antecediendo (int) obtenemos la parte entera de dicho producto):

    public void tirar() {
        valor=1+(int)(Math.random()*6);
    }

Como vemos le sumamos uno ya que el producto del valor aleatorio con seis puede generar números enteros entre 0 y 5.

El método imprimir de la clase Dado muestra por pantalla el valor del dado:

    public void imprimir() {
        System.out.println("El valor del dado es:"+valor);
    }

Por último el método que retorna el valor del dado (se utiliza en la otra clase para ver si los tres dados generaron el mismo valor):

    public int retornarValor() {
        return valor;
    }

La clase JuegoDeDatos define tres atributos de la clase Dado (con esto decimos que la clase Dado colabora con la clase JuegoDeDados):

public class JuegoDeDados {
    private Dado dado1,dado2,dado3;

En el constructor procedemos a crear los tres objetos de la clase Dado:

    public JuegoDeDados() {
        dado1=new Dado();
        dado2=new Dado();
        dado3=new Dado();        	
    }

En el método jugar llamamos al método tirar de cada dado, pedimos que se imprima el valor generado y finalmente procedemos a verificar si se ganó o no:

    public void jugar() {
        dado1.tirar();
        dado1.imprimir();
        dado2.tirar();
        dado2.imprimir();
        dado3.tirar();
        dado3.imprimir();
        if (dado1.retornarValor()==dado2.retornarValor() && 
            dado1.retornarValor()==dado3.retornarValor()) {
            System.out.println("Ganó");
        } else {
            System.out.println("Perdió");
        }        	
    }

En la main creamos solo un objeto de la clase principal (en este caso la clase principal es el JuegoDeDados):

    public static void main(String[] ar){
        JuegoDeDados j=new JuegoDeDados();
        j.jugar();
    }

Problemas propuestos

  1. Plantear una clase Club y otra clase Socio.
    La clase Socio debe tener los siguientes atributos privados: nombre y la antigüedad en el club (en años). En el constructor pedir la carga 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
import java.util.Scanner;
public class Socio {
    private String nombre;
    private int antiguedad;
    
    public Socio(Scanner teclado) {
        System.out.print("Ingrese el nombre del socio:");
        nombre=teclado.next();
        System.out.print("Ingrese la antiguedad:");
        antiguedad=teclado.nextInt();
    }
    
    public void imprimir() {
        System.out.println(nombre+" tiene una antiguedad de "+antiguedad);
    }
    
    public int retornarAntiguedad() {
        return antiguedad;
    }
}



import java.util.Scanner;
public class Club {
    private Socio socio1,socio2,socio3;
    private Scanner teclado;
    
    public Club() {
      teclado=new Scanner(System.in);
      socio1=new Socio(teclado);
      socio2=new Socio(teclado);
      socio3=new Socio(teclado);
    }

    public void mayorAntiguedad() {
    	System.out.print("Socio con mayor antiguedad:");
        if (socio1.retornarAntiguedad()>socio2.retornarAntiguedad() &&
            socio1.retornarAntiguedad()>socio3.retornarAntiguedad()) {
            socio1.imprimir();
        } else {
            if (socio2.retornarAntiguedad()>socio3.retornarAntiguedad()) {
                socio2.imprimir();
            } else {
                socio3.imprimir();
            }
        }
    }
    
    public static void main(String[] ar) {
        Club club1=new Club();
        club1.mayorAntiguedad();
    }
}

Retornar