Una clase compuesta es una clase que tienen entre sus atributos una referencia a otra clase. En este ejercicio vamos a ver un ejemplo de composición de clases.
Vamos a crear dos clases:
Una clase Fecha con los atributos dia, mes y año, todos de tipo int.
Una clase Persona con los atributos: nombre (String), población (String) y fecha de nacimiento. El atributo fecha de nacimiento es de tipo Fecha.
La clase Persona es una clase compuesta porque entre sus atributos hay uno, fechaNacimiento, que es una referencia a un objeto de otra clase, en concreto, es una atributo de tipo Fecha.
Las clases Persona y Fecha tienen por
tanto una relación de composición.
En UML la composición de clases se representa mediante una línea con un rombo junto a la clase compuesta (la clase que contiene el atributo del tipo de la otra clase)
Para ver cómo se trabaja con clases compuestas realizaremos este programa:
Programa que pida por teclado los datos de una serie de personas y los guarde en un ArrayList. El número total de personas a introducir en el ArrayList se introduce por teclado.
A continuación se mostrará por pantalla lo siguiente:
- Todas las personas contenidas en el ArrayList
- La persona de mayor edad. Si hay varias con esa edad se mostrará la primera introducida.
- Todas las personas que viven en una población que se introduce por teclado.
- Número de personas mayores de edad.
Clase Fecha
Comenzamos creando la clase Fecha. Además de los constructores, métodos getters y setters, y método toTring, en esta clase escribiremos un
método boolean esMenorQue(Fecha f) . El método devuelve true si la fecha que
contiene el objeto es menor que la fecha que recibe como parámetro y false en
caso contrario. Este método lo utilizaremos para saber cuál es la persona de mayor edad. Además en la clase Fecha escribiremos un método para comprobar si la fecha es correcta o no.
//Clase Fecha
public class Fecha {
private int dia;
private int mes;
private int año;
//Constructor por defecto
public Fecha() {
}
//Constructor con parámetros
public Fecha(int dia, int mes, int año) {
this.dia = dia;
this.mes = mes;
this.año = año;
}
//Constructor copia
public Fecha(Fecha fecha) {
this.dia = fecha.dia;
this.mes = fecha.mes;
this.año = fecha.año;
}
//Métodos get y set
public int getDia() {
return dia;
}
public void setDia(int dia) {
this.dia = dia;
}
public int getMes() {
return mes;
}
public void setMes(int mes) {
this.mes = mes;
}
public int getAño() {
return año;
}
public void setAño(int año) {
this.año = año;
}
//Método para comprobar si la fecha es correcta
public boolean fechaCorrecta() {
boolean diaCorrecto, mesCorrecto, añoCorrecto;
añoCorrecto = this.año > 0;
mesCorrecto = this.mes >= 1 && this.mes <= 12;
switch (this.mes) {
case 2 -> {
if (esBisiesto()) {
diaCorrecto = this.dia >= 1 && this.dia <= 29;
} else {
diaCorrecto = this.dia >= 1 && this.dia <= 28;
}
}
case 4, 6, 9, 11 -> diaCorrecto = this.dia >= 1 && this.dia <= 30;
default -> diaCorrecto = this.dia >= 1 && this.dia <= 31;
}
return diaCorrecto && mesCorrecto && añoCorrecto;
}
//Método para comprobar si el año es bisiesto
//Método privado invocado desde el método fechaCorrecta
private boolean esBisiesto() {
return (this.año % 4 == 0 && this.año % 100 != 0 || this.año % 400 == 0);
}
//Método para comprobar si la fecha es menor que la que se recibe
public boolean esMenorQue(Fecha f) {
if (this.año < f.año) {
return true;
}
if (this.año == f.año && this.mes < f.mes) {
return true;
}
return this.año == f.año && this.mes == f.mes && this.dia < f.dia;
}
//Método para mostrar la fecha
//Devuelve un String con la fecha en formato dd-mm-aa
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("%02d-%02d-%02d", dia, mes, año));
return sb.toString();
}
} //Final de la Clase Fecha
Clase Persona
Una vez creada la clase Fecha se crea la clase Persona. Además de los constructores, métodos getters y setters y el método toString, en la clase Persona escribiremos un método boolean esMayorDeEdad() que utilizaremos para saber si la persona es mayor de edad o no lo es.
El método toString() de la clase Persona se escribirá de modo que los datos de las personas se muestren de esta forma:
Nombre: Adolfo Pérez Clavarana
Población: Elche
Fecha Nacimiento: 12-07-1987
El atributo fechaNacimiento de la clase Persona representa un objteto de tipo Fecha, pero ese objeto no se crea cuando se escribe el atributo, es decir, no se escribe private Fecha fechaNacimiento = new Fecha();. Por norma general, los objetos que contiene una clase compuesta se crean e inicializan en el constructor. En los atributos de la clase se indica el nombre y tipo pero no se crea el objeto. En este caso, en los constructores de la clase Persona se crearán los objetos de tipo Fecha
import java.time.LocalDate;
//Clase Persona
public class Persona {
private String nombre;
private String poblacion;
private Fecha fechaNacimiento;
//Constructor por defecto
public Persona() {
fechaNacimiento = new Fecha();
}
//Constructor con todos los parámetros
public Persona(String nombre, String poblacion, Fecha fechaNacimiento) {
this.nombre = nombre;
this.poblacion = poblacion;
this.fechaNacimiento = new Fecha(fechaNacimiento);
}
//Métodos get y set
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getPoblacion() {
return poblacion;
}
public void setPoblacion(String poblacion) {
this.poblacion = poblacion;
}
public Fecha getFechaNacimiento() {
return fechaNacimiento;
}
public void setFechaNacimiento(Fecha fechaNacimiento) {
this.fechaNacimiento = new Fecha(fechaNacimiento);
}
//Método para comprobar si la persona es mayor de edad
public boolean esMayorDeEdad() {
LocalDate hoy = LocalDate.now();
int añoActual = hoy.getYear();
int mesActual = hoy.getMonthValue();
int diaActual = hoy.getDayOfMonth();
if (añoActual - fechaNacimiento.getAño() > 18) {
return true;
} else if (añoActual - fechaNacimiento.getAño() == 18 &&
mesActual > fechaNacimiento.getMes()) {
return true;
} else if (añoActual - fechaNacimiento.getAño() == 18 &&
mesActual == fechaNacimiento.getMes() &&
diaActual >= fechaNacimiento.getDia()) {
return true;
}
return false;
}
//Método para mostrar los datos de las personas según el formato pedido
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Nombre: ");
sb.append(nombre);
sb.append("\nPoblación: ");
sb.append(poblacion);
sb.append("\nFecha de Nacimiento: ");
sb.append(fechaNacimiento);
return sb.toString();
}
} //Final de la clase Persona
Clase Principal
Una vez creadas las clases Fecha y Persona, las utilizaremos en la clase principal donde se escriben los métodos necesarios para que el programa realice lo que pide el ejercicio.
El código de la clase principal será este:
import java.util.ArrayList;
import java.util.Scanner;
public class EjemploClaseCompuesta {
//se crea el ArrayList de Personas
static ArrayList<Persona> personas = new ArrayList<>();
//creamos un Scanner para la lectura de datos por teclado
static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
//se introducen las personas en el ArrayList
leerPersonas();
//se muestran todas las personas introducidas
System.out.println("\nPersonas introducidas: ");
mostrarPersonas();
//se muestra la persona de mayor edad
System.out.println("\nPersona de mayor edad: ");
System.out.println(personaDeMayorEdad());
//Se muestra el número de personas que viven en una población
String poblacion;
System.out.println("\nPersonas que viven en una población");
System.out.print("Introduzca población: ");
poblacion = sc.nextLine();
System.out.println("\nNúmero de personas que viven en " + poblacion + ": "
+ cuantasPersonasVivenEn(poblacion));
//se muestra el número de personas mayores de edad
System.out.println("\nNúmero de personas mayores de edad : "
+ personasMayoresDeEdad());
}
//Método donde se crean los objetos Persona
//se introducen sus datos por teclado
//y se añaden los objetos al ArrayList
public static void leerPersonas() {
String nombre, poblacion;
Fecha fecha;
Persona p;
int total, i, dia, mes, año;
//se pide cuántas personas en total vamos a introducir
do {
System.out.print("Número de personas? ");
total = sc.nextInt();
} while (total < 1);
sc.nextLine(); //limpiar el buffer de entrada
//Bucle para crear las Personas, introducir sus datos por teclado
//y almacenarlas en el ArrayList
for (i = 1; i <= total; i++) {
System.out.println("Persona " + i);
//se introduce por teclado el nombre de la persona
System.out.print("Nombre: ");
nombre = sc.nextLine();
//se introduce por teclado la población
System.out.print("Población: ");
poblacion = sc.nextLine();
//se introduce por teclado la fecha de nacimiento: dia, mes y año
do {
System.out.println("Fecha de Nacimiento: ");
System.out.print("Dia: ");
dia = sc.nextInt();
System.out.print("Mes: ");
mes = sc.nextInt();
System.out.print("Año: ");
año = sc.nextInt();
//se crea un objeto Fecha
fecha = new Fecha(dia, mes, año);
} while (!fecha.fechaCorrecta());//se comprueba si la fecha es correcta
sc.nextLine();//limpiar el buffer de entrada
//se crea una nueva instancia de Persona mediante el constructor con parámetros
p = new Persona(nombre, poblacion, fecha);
//también se podría utilizar el constructor por defecto para crear el
//objeto Persona y después asignar los valores de los atributos
//mediante los métodos set.
//se añade el objeto al array
personas.add(p);
}
}
//Mostrar todas las personas
public static void mostrarPersonas() {
for (int i = 0; i < personas.size(); i++) {
System.out.println(personas.get(i));
}
}
//Método que devuelve la persona de mayor edad
//En este método se utiliza el método esMenorQue() de la clase Fecha
public static Persona personaDeMayorEdad() {
Persona mayor = personas.get(0);
for (int i = 1; i < personas.size(); i++) {
if (personas.get(i).getFechaNacimiento().esMenorQue(mayor.getFechaNacimiento())) {
mayor = personas.get(i);
}
}
return mayor;
}
//Calcula y devuelve el número de personas que viven
//en la ciudad que se recibe como parámetro
public static int cuantasPersonasVivenEn(String ciudad) {
int contador = 0;
for (int i = 0; i < personas.size(); i++) {
if (personas.get(i).getPoblacion().equalsIgnoreCase(ciudad)) {
contador++;
}
}
return contador;
}
//Calcula y devuelve el número de personas mayores de edad
//En este método se utiliza el método esMayorDeEdad() de la clase Persona
public static int personasMayoresDeEdad() {
int contador = 0;
for (int i = 0; i < personas.size(); i++) {
if (personas.get(i).esMayorDeEdad()) {
contador++;
}
}
return contador;
}
} //Fin de la Clase Principal
Con este código, el método personaMayorEdad() me devuelve la persona más joven (fecha mayor)
ResponderEliminar******COPY&PASTE DE ARRIBA**********************
//Devuelve la persona de mayor edad
//En este método se utiliza el método esMayorQue() añadido a la clase Fecha
public static Persona personaMayorEdad() {
Persona aux = personas.get(0);
for (int i = 1; i < personas.size(); i++) {
if (personas.get(i).getFechaNacimiento().esMayorQue(aux.getFechaNacimiento())) {
aux = personas.get(i);
}
}
return aux;
}
****************************
He tenido que invertir la condición if
aux.getFechaNacimiento().esMayorQue(personas.get(i).getFechaNacimiento())
Para que me devuelva la persona de más edad.
.
ResponderEliminarExcelente codigo,,, aunque se podria modificar para los statics.
ResponderEliminarUn hospital desea un programa donde se genere el importe que se debe cobrar a los
ResponderEliminarpacientes. El hospital ofrece los siguientes servicios:
Consulta con médico general->$340 por consulta
Consulta con médico especialista->$800 por consulta
Curaciones->$200 por servicio
El hospital es especial, hace sus cobros a los pacientes cada 8 días, por lo que se
pueden acumular las consultas y curaciones.
Las personas mayores de 60 años reciben un descuento del 10% en su importe total.
Proyecto Hospital
Clase clsCalculos:
Método Subtotal(Recibe el número de consultas con médico general,
número de consultas con médico especialista y número de curaciones) Retorna el
subtotal
Método Descuento(Recibe el subtotal ) retorna el importe de descuento
NOTA: Este método es invocado solamente si el paciente es mayor de 60
años
Muy bien el código, el único inconveniente es con el método personaMayorEdad(). Solo me devuelve la fecha mayor, mas no la edad.
ResponderEliminar