Capitulo2POOEnJava
Capitulo2POOEnJava
1
CAPÍTULO II: PROGRAMACIÓN ORIENTADA AL
OBJETO CON JAVA
Modularidad:
Permite subdividir una aplicación en partes más pequeñas (llamados
módulos), cada una de las cuales debe ser tan independientes como sea
posible de la aplicación en sí y de las restantes partes.
Por lo tanto, una aplicación en Java queda formada por código que está en
distintos paquetes y cada paquete puede tener varios archivos con
extensión .java
2.4
Brecha
Semántica
Casa Auto
Vive en Conduce
Modelo un Árbol
Tom
2.5
En la etapa de análisis aparecen los objetos del dominio del problema, es
decir, los objetos del mundo real.
Especificación de la
solución
Objetos definidos durante el
diseño
¿Cómo?
2.6
2.2. Modelo del dominio
“El modelo de dominio representa las “cosas” que existen o eventos que
transcurren en el entorno de un negocio.” [I. Jacobsen]
Concepto de relacionamiento
Ejemplo
Para un problema dado, se pueden efectuar las siguientes aseveraciones:
Un cliente coloca cero o más ordenes de compra.
Una orden de compra es colocada por uno y sólo un cliente.
1 Coloca *
Cliente Orden
Tipos de multiplicidad
1
Concepto 1 y sólo 1
* Concepto 0 ó más
n..m
Concepto
Entre n y m
2.9
1..*
Concepto 1 o más
3,5,8
Concepto Exactamente 3, 5
u ocho
5
Concepto Exactamente 5
Ejemplos
1..* pertenece 1
Profesor Depto
1..* pertenece 1
Estudiante Carrera
Medicamento
Comprobante de pago
2.13
Asociaciones
1..*
1..*
1..* 1..*
2.14
Atributos
nombre rut
dirección
rut
1..*
1..*
1..*
tipo
rut
2.15
El Modelo del Dominio se obtiene identificando:
1. Entidades
a. Nombre
b. Propiedades o características
2. Relaciones
a. Nombre
b. Dirección
c. Cardinalidad
3. Restricciones
Problema Tutores
En los últimos años la Universidad Católica del Norte se ha preocupado
por el rendimiento de sus alumnos y ha puesto en marcha el plan piloto
“Tutores” en algunas carreras específicas. Cómo el número de carreras ha
sido pequeño, toda la información del plan ha sido realizada a mano hasta
el momento. El plan ha dado como resultado una mejora superior a lo
esperado, es por ello, que la UCN ha decidido expandir el plan al resto de
los alumnos.
2.16
Modelo del Dominio
Area de especialización
2.17
Modelo del Dominio
Area de especialización
Alumno tutelado
asiste
Alumno tutor
2.18
Modelo del Dominio
Area de especialización
Alumno tutelado
tutelado
asiste
Alumno tutor
2.19
Modelo del Dominio
¿Tiene restricciones?, ¿Cuáles?
Restriciones Tutores
Nombre del alumno no puede ser inferior a 2 letras.
Rut del alumno debe ser válido.
Nota de enseñanza media debe estar en el intervalo 1.0 – 7.0. Se
aceptan las notas con un dígito decimal.
Puntaje de ingreso debe ser un valor entero entre 500 y 900 puntos.
Semestre que cursa debe ser un valor entre 1 y 14.
Un alumno sólo puede ser tutor si ha cursado a lo menos dos
semestres de su carrera y posee menos de cinco asignaturas inscritas
en el semestre.
…
Operaciones en el modelo del dominio
En el modelo del dominio se pueden colocar operaciones cuando éstas
son parte del modelo del negocio y son calculables. A este nivel, en el
análisis se está preocuado de los conceptos, atributos y relacionamientos y
normalmente no estamos preocupados de identificar las operaciones
Operaciones Tutores
Obtener la cantidad de horas en que el tutor realizó la tutela.
Calcular el incentivo que le corresponde.
2.20
Modelo del Dominio + Operaciones
asiste
Calcular horas()
Calcular incentivo()
2.21
Ejercicio
Se debe construir una aplicación maneje los proyectos en los que trabaja
un empleado. En un proyecto trabajan muchos empleados y un empleado
puede trabajar en varios proyectos. Es importante saber cuántas horas a la
semana le dedica cada empleado a cada uno de los proyectos en que
trabaja .
* trabajan 1..*
Proyecto Empleado
Código proyecto Rut empleado
Nombre proyecto Nombre empleado
Dedicacion
horas a la semana
Otra forma
1..* *
Dedicacion
horas
2.22
Ejercicio
Se debe construir una aplicación para que el jefe de carrera de ICCI pueda
inscribirle a los estudiantes de la carrera las asignaturas de un determinado
semestre. Para esto el jefe de carrera atiende a cada uno de los estudiantes
en su oficina, utilizando la aplicación para la inscripción. Cabe señalar que
cuando el jefe de carrera le inscribe una asignatura a un estudiante, debe
indicar en qué oportunidad la está inscribiendo. De una asignatura interesa
el código, nombre y créditos. De un estudiante, su rut y nombre. Esta
aplicación tendrá como usuario solo al jefe de carrera.
Construya el modelo del dominio
1..* inscribe 1..*
Estudiante Asignatura
nombre codigo
rut nombre
Inscripcion creditos
oportunidad
*
Jefe de Carrera ICCI
1
realiza
Otra forma
Estudiante
1 Asignatura
tiene tiene
Rut 1
Código
Nombre Nombre
Créditos
1..* 1..*
realiza Inscripcion
Jefe de Carrera 1 Oportunidad
*
2.23
2.3. Conceptos de orientación al objeto
2.3.1. Cinco palabras claves del vocabulario O.O
Ejemplo:
Clase con sus atributos:
Persona
nombre: String
edad : int
2.24
Objetos con sus valores
p1: Persona p2: Persona
Objeto:
Ejemplos de Clases:
Puerta Para una empresa que fabrica puertas y ventanas
Empleado Para un sistema de remuneraciones
Habitación Para un sistema de reservas de un hotel
Vehículo Para un sistema de arriendo de vehículos
Ejemplos de Atributos:
Puerta largo
ancho
espesor
tipo de madera
2.26
Empleado rut
nombre
dirección particular
fono particular
fono empresa
Habitación número
cantidad de camas
metros cuadrados
citófono
valor
Vehículo patente
marca
modelo
año
Ejemplo de Comportamiento:
Puerta abrir
cerrar
poner llave
sacar llave
2.27
Ejercicio
Se tiene que hacer un programa que maneje información de los alumnos y
profesores de la UCN. Identifique las clases e indique para ellas atributos y
comportamiento. Muestre para cada una de las clases identificadas, 2
ejemplos de objetos.
Alumno Profesor
numeroMatricula: String nombre: String
nombre: String tipo: int
edad : int
Diagrama de clase
A diferencia del modelo del dominio, el Diagrama de Clases es para el
diseñador del software
Nombre de Clase
Visibilidad tipo de dato 1 nombre atributo 1
Visibilidad tipo de dato 2 nombre atributo 2
...
Ejemplo:
Persona
- private - String nombre
+ public - int edad
+ Persona(String nom, int edad)
+ getEdad(): int
+ getNombre(): String
+ setEdad(int edad)
+ setNombre(String nombre)
2.30
2.3.3. Variables y Métodos de Instancia, Variables y Métodos de Clase
Variable de Instancia:
Una variable de instancia pertenece a una instancia. Su valor sólo
puede ser cambiado por operaciones que pertenecen a la instancia.
Variable de Clase:
Variable compartida por todas las instancias de una clase (una ÚNICA
copia).
Todos los objetos de la clase la pueden ver.
CuentaAhorro
Variable de instancia
- int numero Cada objeto tiene su
- int saldo número y saldo
- $ double interes
Variable de clase
Todas las instancias ven el
interés. Es el mismo para
todos los objetos
2.31
Métodos de instancia:
Pertenece a un objeto.
Métodos de clase:
Está asociado a una clase.
Ejemplo:
Variables de instancia
CuentaAhorro
Variable de clase
- int numero
- int saldo
- $ double interes
Método de instancia
+ getNumero(): int
+ $ getInteres(): double
Método de clase
Forma de invocación:
c.getNumero() c es un objeto de la clase CuentaAhorro
CuentaAhorro.getInteres()
2.32
2.3.4. Operaciones sobre un objeto
Modificador
Obtenedor
Constructor
Destructor
NombreClase nombreVariable;
B. Creación de objetos
Un objeto en JAVA, se construye únicamente por la expresión de creación
dinámica, que tiene la forma:
D. Comparación de Objetos
Ejemplo de identidad:
x y
String x = "a";
String y = "a"; a
x = y; if ( x == y) true
x y
int x, y
x y
if (x = = y) verdadero
5 5
E. Destrucción de objetos
En Java no existe el concepto de destructor explícito de objetos.
Alumno
- String nombre
- String rut
@Override
public String toString() {
return "Alumno [nombre=" + nombre + ", numeroMatricula=" +
numeroMatricula + "]";
}
}
2.38
Ejemplo de programa en Java
Se desea manejar la información de las cuentas bancarias de un banco. Una
cuenta tiene un saldo. Se puede depositar y girar sobre la cuenta bancaria.
La aplicación debe hacer un depósito sobre una cuenta y luego un giro sobre
la misma cuenta. Una vez hechas las transacciones sobre la cuenta, se debe
desplegar su saldo. Considere que la cuenta se crea inicialmente con un saldo
cero y luego se debe leer un valor desde pantalla que corresponderá al saldo
de la cuenta
Diagrama de clases
CuentaBancaria Nombre de la Clase
- int saldo Variable de Instancia
+ CuentaBancaria(int saldoInicial)
+ depositar(int cantidad)
+ girar(int cantidad): boolean
+ getSaldo(): int Métodos de Instancia
+ setSaldo(int saldoNuevo)
+ toString(): String
@Override
public String toString() {
return "CuentaBancaria [saldo=" + saldo + "]";
}
}//Fin cuentaBancaria
2.40
import ucn.StdOut;
Se imprime
Saldo antes de las transacciones: 100
Cuenta bancaria antes de las transacciones:CuentaBancaria [saldo=100]
Despues de las transacciones: 154
Cuenta bancaria despues de las transacciones: CuentaBancaria [saldo=154]
cuentaBancaria: CuentaBancaria
saldo = 0
Diagrama de 100
objetos 174
154
2.41
Ejercicio
Dado el siguiente diagrama de clases, complételo y escriba en Java la clase
Asignatura y un programa Java que cree un objeto Asignatura cuyo código
es “cc 571” y créditos = 14. Una vez creado el objeto se debe desplegar por
pantalla sus datos.
Asignatura
codigo
creditos
Asignatura()
getCodigo()
getCreditos()
setCodigo() No todo atributo
setCreditos() debe tener el
método set
Solución
Asignatura
- String codigo
- int creditos
+ Asignatura(String cod, int cred)
+ getCodigo(): String
+ getCreditos(): int
+ setCodigo(String cod)
+ setCreditos(int cred)
2.42
public class Asignatura {
private String codigo;
private int creditos;
Ejemplo
El programa siguiente, crea dos objetos Punto diferentes y pone valores
únicos en cada uno.
Recuerde que si no hay rutina
public class Punto { constructora, existe un constructor
private int x; por defecto que crea el espacio y
coloca los valores por defecto para
private int y;
los atributos de la clase.
public void init (int xx, int yy) {
x = xx;
y = yy;
}
public void setX(int xx){
x = xx;
}
Punto
public void setY(int yy){
y = yy; - int x
} - int y
public int getX(){
return x; + setX(int xx)
} + setY(int yy)
public int getY(){ + getX(): int
return y; + getY(): int
}
} Podríamos tener el método toString()
2.44
public class DosPuntos {
p1.setX(10);
p1.setY(20);
p2.setX(42);
p2.setY(99);
p3.init(10, 20);
p4.init(42, 99);
x = 0 10 x = 0 42 x = 10 x = 42
y = 0 20 y = 0 99 y = 20 y = 99
Imprime
x = 10 y = 20
x = 42 y = 99
x = 10 y = 20
x = 42 y = 99
2.46
Ejemplo 1:
Inicializar las variables de una clase, utilizando el constructor.
Ejemplo 2:
Empleado
…
Por lo tanto la clase Punto debe tener 2 versiones del método distancia:
Una que tiene como parámetro un objeto de la calse Punto
Una que tiene como parámetro 2 valores enteros que representan las coordenadas
de un punto
Punto
- int x
- int y
+ Punto(int x, int y)
+ setX(int x)
+ setY(int y)
+ getX(): int
+ getY(): int
+ distancia(int x, int y): double
+ distancia(Punto p): double
2.49
public class Punto {
private int x;
private int y;
Ejemplo 3: Versión de la clase Punto que utiliza la sobrecarga de método para crear
un constructor alternativo que establece algunos valores por omisión para las
coordenadas x e y.
public class Punto {
private int x;
private int y;
public Punto(int x, int y) {
this.x = x;
this.y = y;
}
public Punto() {
x = -1;
y = -1;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
Ejemplo
Para un problema dado, se pueden efectuar las siguientes aseveraciones:
Un cliente coloca cero o más ordenes de compra.
Una orden de compra es colocada por uno y sólo un cliente.
1 *
Cliente Orden
* Clase 0 ó más
n..m
Clase Entre n y m
Agregación Composición
Independencia Dependencia
Tiene-un Parte-de
Débil Fuerte
a. Agregación
Una clase especial de relacionamiento puede existir entre objetos / clases:
Algunas veces los objetos / clases están formados por otros objetos.
Auto:
Transmisión
Tubo de escape
Motor
Suspensión
Ruedas
Ventana:
Botones
Labels
Menús
Ejemplo 1: Computador
1 1 1 1
Monitor Caja Mouse Teclado
sistema
1 1 1 1
Chassis Cpu RAM Ventilador
2.54
Ejemplo 2: Libro
1 0..1 1..* 1
Cubierta Tabla de Capítulo Indice
contenido
s
1..*
Pagina
1..*
Párrafo
1..*
Palabra
b. Composición
A * B
Compuesto Componente
Ejemplo: Se necesita una aplicación que maneje los datos de los estudiantes de la UCN, sede
Coquimbo.
ListaEstudiantes * Estudiante
- double [ ] lista - String rut
- String nombre
- int cantidadEstudiantes + Estudiante(String rut, String nombre)
- int max + get y set….
+ ListaEstudiantes(int max)
+ buscar(String rut): Estudiante
+ ingresar(Estudiante estudiante): boolean
+ eliminar(String rut): boolean
+ getCantidadEstudiantes(): int
+ getEstudiante(int i): Estudiante
if (pos != -1){
//Corrimiento
for(int k=j; k<cantidadElementos - 1;k++){
lista[k] = lista[k+1];
}
cantidadElementos--; // decrementa tamaño
return true;
}
else{
return false;
}
}
2.59
public class ListaDoublesApp {
public static void main(String[] args){
int tamMaximo = 100; // tamaño máximo
ListaDoubles ld; // referencia al arreglo
ld = new ListaDoubles(tamMaximo);//crea el contenedor
ld.insertar(77); // inserta 10 items
ld.insertar(99);
ld.insertar(44);
ld.insertar(55);
ld.insertar(22);
ld.insertar(88);
ld.insertar(11);
ld.insertar(00);
ld.insertar(66);
ld.insertar (33);
//Despliga los items del contenedor
for (int i =0; i <ld.getCantidadElementos ();i++){
StdOut.println(ld.getElemI(i));
}
int claveBusqueda = 35; // busca el item
if( ld.encontrar(claveBusqueda)!= -1){
StdOut.println("Encontrado " + claveBusqueda);
}
else {
StdOut.println("No Encontrado " + claveBusqueda);
}
ld.eliminar(00); // elimina 3 items
ld.eliminar(55);
ld.eliminar(99);
//Despliega los items del contenedor
for (int i =0; i <ld.getCantidadElementos (); i++){
StdOut.println(ld.getElemI(i));
}
} // end main()
@Override
public String toString() {
return "Persona [apellido=" + apellido + ", nombre=" +
nombre + ", edad=" + edad + "]";
}
}//Fin Persona
import ucn.StdOut;
public class ListaPersonasApp {
public static void desplegarPersonas(ListaPersonas
listaPersonas){
// despliega los items
StdOut.println("Despliegue de las personas");
for(int i=0; i<listaPersonas.getCantidadPersonas();i++){
Persona p = listaPersonas.getPersonaI(i);
StdOut.println(p.getApellido() + " " +
p.getNombre() + " " +p.getEdad());
}
StdOut.println();
}
// inserta 10 items
Persona p = new Persona("Martinez", "Jose", 24);
listaPersonas.ingresarPersona(p);
Persona p9 = new Persona("Tapia","Luis",37);
listaPersonas.ingresarPersona(p9);
Persona p1 = new Persona("Viorklumds", "Jorge", 43);
listaPersonas.ingresarPersona(p1);
Persona p2 = new Persona("Ferrada", "Cecilia", 63);
listaPersonas.ingresarPersona(p2);
Persona p3 = new Persona("Vega","Carlos",21);
desplegarPersonas(listaPersonas);
StdOut.println("Despliegue de las personas");
StdOut.println(listaPersonas.toString());
StdOut.println();
2.65
StdOut.println("Buscando a Martinez");
String apellido = "Martinez"; // busca el item
Persona found=listaPersonas.buscarPersona(apellido);
if(found != null){
StdOut.print("Encontrado ");
StdOut.println(found.getApellido() + " " +
found.getNombre() +" " + found.getEdad());
}
else {
StdOut.println("No encontrado " + apellido);
}
StdOut.println();
desplegarPersonas(listaPersonas);
}//Fin main
Se imprime:
Buscando a Martinez
Encontrado Martinez Jose 24
// inserta 4 items
Persona p = new Persona("Martinez", "Jose", 24);
listaPersonas.ingresarPersona(p);
p = new Persona("Tapia","Luis",37);
listaPersonas.ingresarPersona(p);
p = new Persona("Viorklumds", "Jorge", 43);
listaPersonas.ingresarPersona(p);
p = new Persona("Ferrada", "Cecilia", 63);
listaPersonas.ingresarPersona(p);
listaPersonas
Con:
Persona p = new Persona("Martinez", "Jose", 24);
listaPersonas.ingresarPersona(p);
cantidadPersonas
0
1
Persona
apellido: Martinez
nombre: Jose
edad: 24
p = listaPersonas[0]
2.68
Con:
p = new Persona("Tapia","Luis",37);
listaPersonas.ingresarPersona(p);
cantidadPersonas
0
1
2
Persona Persona
apellido: Martinez apellido: Tapia
nombre: Jose nombre: Luis
edad: 24 edad: 37
p ≠ listaPersonas[0] p = listaPersonas[1]
Persona
El objeto apellido: Martinez no es basura, ya que se puede llegar a él a través de
nombre: Jose
edad: 24
listaPersonas[0]
2.69
2.5.2. Ordenamiento de un contenedor de objetos
Persona * ListaPersonas
- String apellido - Persona [] lista
- String nombre - int cantidadPersonas
- int edad + ListaPersonas(int max)
+ insertar(Persona persona): boolean
+ Persona(String apellido,
+ ordenamientoSimple()
String nombre, int edad)
+ getCantidadPersonas(): int
+ get y set …. + getPersona (int i): Persona
+ toString(): String + toString(): String
// get y set ….
// toString()….
} //fin ordenamientoSimple
//toString()....
ingresarPersonas(listaPersonas);
StdOut.println(“Antes de ordenar:”) ;
desplegarPersonas(listaPersonas); Se podría desplegar la
lista de personas usando
listaPersonas.ordenamientoSimple(); el método toString(),
como en el caso del
StdOut.println(“Despues de ordenar:”) ; ejemplo anterior
desplegarPersonas(listaPersonas);
}//fin main()
Ejercicio
Un médico tiene rut, nombre, registro médico y especialidad. Un paciente
tiene rut, nombre, diagnóstico y médico de cabecera (sólo 1).
Para este problema, se deben tener 2 objetos, uno de la clase Paciente y otro
de la clase Medico. Es necesario poder llegar desde el paciente a su médico
para poder realizar el requerimiento (d). Esto significa que se necesita poder
navegar desde paciente a médico.
Entonces,
Se pueden agregar flechas en los relacionamientos para indicar
navegabilidad.
1
Orden* Cliente
Compra
1 1
A B
A B
Ref. B. Ref. A.
Retomando el ejercicio
Un médico tiene rut, nombre, registro médico y especialidad. Un paciente
tiene rut, nombre, diagnóstico y médico de cabecera (sólo 1).
1 *
Médico Paciente
atiende
Rut Rut
Nombre Nombre
Registro médico Diagnóstico
especialidad
Medico Paciente
1 *
- String rut - String rut
- String nombre - String nombre
- String registroMedico - String disgnostico
- String especialidad - Medico medico
+ Paciente ()
+ Medico() + setDiagnostico(String diagnostico)
+ get y set …. + getMedico(): Medico
+ toString(): String + setMedico(Medico medico)
+ toString(): String
2.76
Refino de la solución
main( ) {
Crear el objeto médico
Crear el objeto paciente
Ingresar diagnóstico del objeto paciente
Asociar el objeto médico al objeto paciente
}
//get y set ….
//toString()…
//toString() ….
Diagrama de Objetos
rut=111-k rut=222-1
registroMedico=151-5 diagnostico=Apendicitis
especialidad=cardiologo medico
2.79
2.6.3. Implementación de una asociación 1:N y/o N:N
Ejercicio
Se necesita manejar información de un país y sus ciudades. Para un país
interesa saber su nombre, idioma y cantidad de habitantes. Para una ciudad,
su nombre, alcalde (suponga que sólo 1 alcalde por ciudad) y cantidad de
habitantes. Se pide que haga un programa en Java que:
a. Ingrese el país Chile. Suponga que tiene 18.000.000 de habitantes.
b. Ingrese N ciudades de Chile, donde N se lee desde pantalla (lea desde
pantalla los datos de cada ciudad)
c. Una vez ingresada la información del país y sus ciudades, despliegue el
nombre del país y el nombre de cada una de sus ciudades.
Para este problema, se debe crear un objeto país y varios objetos de la clase
Ciudad. Es necesario poder llegar desde el país a sus ciudades para poder
realizar el requerimiento (c). Esto significa que se necesita poder navegar
desde paciente a sus ciudades
Asociación 1: N
1 1..n
A B
A B
Conjunto Ref. A.
de ref.
2.80
Asociación N: N
1..n 1..n
A B
A B
Conjunto Conjunto
Ref. B. Ref. A.
Retomando el ejercicio
Se necesita manejar información de un país y sus ciudades. Para un país
interesa saber su nombre, idioma y cantidad de habitantes. Para una ciudad,
su nombre, alcalde (suponga que sólo 1 alcalde por ciudad) y cantidad de
habitantes. Se pide que haga un programa en Java que:
a. Ingrese el país Chile. Suponga que tiene 18.000.000 de habitantes.
b. Ingrese N ciudades de Chile, donde N se lee desde pantalla (lea desde
pantalla los datos de cada ciudad)
c. Una vez ingresada la información del país y sus ciudades, despliegue el
nombre del país y el nombre de cada una de sus ciudades.
Se pide:
Modelo del dominio
Diagrama de clases del dominio de la aplicación
Código
2.81
Modelo del dominio
1 1..*
País Ciudad
Nombre tiene Nombre
Idioma Alcalde
Cantidad de habitantes Cantidad de habitantes
Diagrama de Objetos
c: Ciudad
nombre= Santiago
alcalde= Alessandri
cantidadHabiatntes= 6000000
p: Pais
c: Ciudad
nombre= Chile
nombre= Antofagasta
idioma=Español
cantidadHabitanes=18000000 alcalde= Rojo
cantidadHabitantes= 400000
listaCiudades
cantidadCiudades= 3 c: Ciudad
nombre= Concepcion
alcalde= Ortiz
cantidadHabitantes= 1000000
2.86
Otra solución del mismo problema
Diagrama de Clases del dominio de la aplicación
Pais Ciudad
- String nombre - String nombre
- String idioma - String alcalde
- int cantidadHabitantes - int cantidadHabitantes
- ListaCiudades listaCiudades + Ciudad(String nombre,
String alcalde,
+ Pais( String nombre, String idioma, int cantidadHabitantes)
int cantidadHabitantes, int max) + get y set()…
+ get y set()…. + toString(): String
+ getListaCiudades(): ListaCiudades
+ toString(): String *
1
ListaCiudades
- Ciudad [] lc
- int cantidadCiudades
- int max
+ ListaCiudades(int max )
+ getCantidadCiudades(): int
+ insertarCiudad(Ciudad ciudad):
boolean
+ getCiudad (int i): Ciudad
+ toString(): String
nombre codigo
rut nombre
Inscripcion creditos
oportunidad
Otra forma
Estudiante Asignatura
tiene tiene
1 1
Rut Código
Nombre Nombre
Créditos
1..* 1..*
Inscripcion
Oportunidad
ListaEstudiantes
- int cantidadEstudiantes 2.92
- Estudiante [] lista
Diagrama de clases - int max
+ ListaEstudiantes(int max)
+ ingresar(Estudiante estudiante):
boolean
+ buscar(String rut): Estudiante
+ eliminar(String rut): boolean
+ getEstudianteI(int i): Estudiante
+ getCantidadEstudiantes(): int
+ setCantidadEstudiantes (
int cantidadEstudiantes)
+ getMax(): int
1 *
ListaInscripciones * Estudiante
Inscripcion 1 - String rut
- int cantidadInscripciones - int oportunidad
- Inscripcion [] lista - String nombre
- Asignatura asignatura - ListaInscripciones listaInscripciones
- int max - Estudiante estudiante
+ ListaInscripciones(int max) Los + Estudiante(String rut, String nombre)
+ Inscripcion(int oportunidad) + getRut(): String
+ ingresar(Inscripcion inscripcion): parámetros
+ getOportunidad(): int + setRut(String rut)
boolean dependerán
+setOportunidad(int oportunidad) + getNombre(): String
+ buscar(): Inscripcion del criterio
+ getEstudiante(): Estudiante + setNombre (String nombre)
+ eliminar(): boolean por el que se
+setEstudiante(Estudiante estudiante)
+ getInscripcionI(int i): Inscripcion quiera buscar + getListaInscripciones(): ListaInscripciones
+ getAsignatura(): Asignatura + setListaInscripciones(ListaInscripciones
+ getCantidadInscripciones(): int y eliminar
+ setAsignatura(Asignatura listaInscripciones)
+ setCantidadInscriciones(
asignatura)
int cantidadInscripciones)
+ getMax(): int 1
+ setMax(int max) 1
Asignatura
ListaAsignaturas - String codigo
- int cantidadAsignaturas - String nombre
* - int creditos
- Asignatura [] lista
- int max - ListaInscripciones listaInscripciones
+ ListaAsignaturas(int max) + Asignatura(String código, String nombre,
+ ingresar(Asignatura asignatura): boolean int creditos)
+ buscar(String codigo): Asignatura + getCodigo(): String
+ setCodigo(String codigo)
+ eliminar(String codigo): boolean
Se podrían tener el + getNombre(): String
+ getAsignaturaI(int i): Asignatura + setNombre (String nombre)
+ getCantidadAsignaturas(): int método toString() en + getCreditos(): int
+ setCantidadAsignaturas ( + setCreditos(int creditos)
int cantidadAsignaturas) cada una de las clases + getListaInscripciones(): ListaInscripciones
+ getMax(): int + setListaInscripciones(
+ setMax(int max) ListaInscripciones listaInscripciones)
2.93
2.7. Interfaces
Problema
Imaginemos que vamos a crear un programa para conducir unos vehículos con ruedas.
En particular, la persona dueña de estos vehículos usa uno diferente para ir a trabajar
dependiendo del día de la semana.
Una de las primeras cosas que podemos concluir, a partir de nuestro conocimiento de
cómo operan diferentes vehículos, es que en todos los casos, podemos avanzar y
frenar, además de girar a la izquierda y derecha. Independiente de cómo realizan la
acción, esto corresponde a la forma en que los humanos interactúan con la máquina. El
detalle interno de cómo un vehículo particular realiza la acción no debería
preocuparnos (por lo menos, hasta más adelante): tal vez un vehículo acelera usando
un carburador, otro puede ser 100% electrónico, o incluso podría ser a vapor (lo que
implicaría echarle carbón a la caldera y abrir válvulas para dejar pasar el vapor).
Es decir, cualquiera sea el vehículo tiene que avanzar, frenar, girar a la izquierda y
girar a la derecha.
Concepto de interfaz
Java admite un concepto similar a la clase, llamado interfaz.
Una interfaz es una colección de métodos abstractos. Un método abstracto no tiene
código.
Una interfaz puede ser pública o privada.
Todos los métodos dentro de la interfaz son públicos y abstractos (no se encuentran
implementados).
Las variables de clase en una interfaz, si es que existen, son implícitamente finales,
públicas y estáticas (en otras palabras, son constantes).
Una interfaz permite al programador describir un conjunto de capacidades que debe
implementar una clase.
Una clase que implementa una interfaz, no está heredando nada. Simplemente, se
compromete a implementar los métodos definidos en la interfaz.
Este es el origen de la palabra clave implements.
2.94
Polimorfismo en JAVA: Una variable declarada de una cierta interface, puede
mantener valores en cualquier clase, que implementa la interface.
Diagrama de clase
En un diagrama de clases, el “estereotipo” es una marca que se coloca sobre el
título o sobre una relación para indicar su comportamiento, por ejemplo
<<interface>>.
En general las clases e interfaces siempre están relacionadas, en este caso, se indica
por una línea segmentada, que indica una relación débil de dependencia
Ejemplo 1
Diagrama de clases
<<interface>>
ListaEstudiantes
+getElemento(int posicion): Estudiante
+buscarElemento(Estudiante elemento): int
+insertarElemento(Estduiante elemento): boolean
+eliminarElemento(int posicion): boolean
+limpiar()
+isVacia():boolean
+getTamanio(): int
<<implements>>
ListaArregloEstatico * Estudiante
- Estudiante [] arreglo - int rut
- int posicionUltimoElemento - String nombre
- String apellido
- String direccion
….
2.95
public class Estudiante {
private int rut;
private String nombre;
private String apellido;
private String direccion;
public Estudiante() {
}
public String getApellido() {
return this.apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getDireccion() {
return this.direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
public String getNombre() {
return this.nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public int getRut() {
return this.rut;
}
public void setRut(int rut) {
this.rut = rut;
}
//toString()….
}//Fin Estudiante
2.96
/**
* Interface que representa el comportamiento de una lista de
* Estudiantes. Esta puede ser implementada de la forma que se desee,
* en este caso a través de un arreglos estáticos (vector)
*
* Se podría querer implementar la lista de estudiantes de otra forma
*/
/**
* Metodo que dada la posicion de un elemento dentro de la lista
* retorna el elemento en esa posicion.
*Si la posicion en la lista no existe retorna null.
* @param posicion
* @return Estudiante/null
*/
public Estudiante getElemento(int posicion);
/**
* Metodo que dado un elemento retorna la posicion en la cual se
* encuentra dentro de la lista. Retorna -1 si el dato no se encuentra.
* @param elemento
* @return int posicion del elemento dentro de la lista.
*/
public int buscarElemento(Estudiante elemento);
/**
* Metodo que inserta un elemento al final de la lista, retorna true si
* fue exitosa la insercion (hay espacio para almacenarlo) o false si
* la lista se encuentra llena.
* @param elemento
* @return boolean true/false
*/
public boolean insertarElemento(Estudiante elemento);
2.97
/**
* Metodo que elimina el elemento en la "posicion" de la lista.
* Si la posición no existe, retorna falso. En caso contrario
* elimina el dato y retorna true.
* @param posicion
* @return boolean true/false
*/
public boolean eliminarElemento(int posicion);
/**
* Metodo que elimina todos los datos de la lista, es decir la
* deja vacia
*/
public void limpiar();
/**
* Metodo que retorna true si y solo si no hay ningún elemento
* presente en la lista
* @return boolean (true/false)
*/
public boolean isVacia();
/**
* Metodo que retorna la cantidad de elementos que posee la lista,
* por ejemplo: Si la lista se encuentra vacia retorna 0;
* @return int cantidad de elementos en la lista.
*/
public int getTamanio();
/**
* Constructor de la clase ListaArregloEstatico
* @param _capacidadMaxima : Cantidad maxima de elementos
* que puede almacenar esta lista.
*/
public ListaArregloEstatico(int capacidadMaxima) {
this.arreglo = new Estudiante[capacidadMaxima];
this.posicionUltimoElemento = -1;
}
//Buscar al alumno 2
StdOut.println("Estudiante 2 encontrado en posicion:" +
lista.buscarElemento(estudiante2));
} //Fin main
interface Vehículo {
void acelerar(); Vehiculo
void frenar(); <<interface>>
acelarar()
void girarDerecha(); frenar()
void girarIzquierda(); girarDerecha()
} girarIzquierda
for(int i=0;i<100;i++) {
if (i % 2 == 0) {
ve.acelerar();
} else if (i % 3 == 0) {
ve.frenar();
} else if (i % 5 == 0) {
ve.girarIzquierda();
} else if (i % 7 == 0) {
ve.girarDerecha();
}
}
}
class Caballo {
public void acelerar() { }
public void frenar() { }
public void indicarDerecha() { }
public void indicarIzquierda() { }
}
@Override Vehiculo
public void acelerar(){ <<interface>>
acelarar()
motorIzquierda.acelerar();
frenar()
motorDerecha.acelerar(); girarDerecha()
} girarIzquierda
@Override <<implements>>
public void frenar(){
motorIzquierda.frenar(); TeslaE3
motorDerecha.frenar(); - Motor motorIzquierda
} - Motor motorDerecha
@Override
public void girarDerecha(){
motorIzquierda.acelerar();
motorDerecha.frenar();
}
@Override
public void girarIzquierda(){
motorIzquierda.frenar();
motorDerecha.acelerar();
}
}
2.105
Supondremos que este vehículo tiene tracción delantera, y que tiene un motor conectado a
cada rueda, por lo tanto para cumplir las operaciones de la interfaz, la secuencia de pasos que tiene
que realizar es diferente (respecto al vehículo tirado por un caballo), pero igual cumple cada
operación.
Desde el punto de vista del “usuario” de la interfaz, no hay diferencia entre ambos tipos de
vehículos: ambos operan de la misma forma. Ahora podemos descomentar las líneas para crear las
clases específicas de vehículos:
Como ejercicio, se pueden completar las operaciones de las clases Motor y Caballo para que
escriban por pantalla mensajes apropiados cada vez que sus métodos son llamados.
2.106
Ejemplo 3
Como se dijo anteriormente, las interfaces permiten definir el contrato que una clase debe cumplir.
Esta es una cualidad que puede ser usada de diferentes maneras, y en particular lo
ejemplificaremos usando algo que el mismo Java trae.
En Java se pueden crear interfaces gráficas de usuario (GUI en inglés). En otras palabras, se
pueden crear ventanas, botones y todo lo que se necesita para crear aplicaciones visuales.
Por ejemplo, este código:
import javax.swing.JFrame;
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
}
Ahora, ¿qué tiene que ver esto con las interfaces? La respuesta se relaciona con un concepto que se
llama Eventos.
¿Qué es un evento?
Cuando creamos interfaces gráficas, siempre necesitaremos responder a las acciones que el usuario
hace en la pantalla. Por ejemplo, presionar un botón. Si el usuario presiona un botón, significa que
2.107
se va a generar el evento “presionar el botón” y de alguna forma tenemos que escribir código
que responda a dicho evento y haga lo que tenga que hacer.
En el caso de Java, al usar las clases de Swing (son las clases que contienen la funcionalidad para
crear componentes gráficos), el sistema de manejo de eventos se diseñó basándose en interfaces.
Hay otros lenguajes en que esto se implementa de otras maneras, pero en el caso de Java, sus
diseñadores decidieron que se implementaría así.
En términos prácticos, en Swing, cuando se desea responder a cierto tipo de eventos, se le debe
indicar al componente (por ejemplo, un botón) que queremos realizar acciones cuando el evento
suceda. Eso se realiza invocando un método en el componente y pasándole como parámetro una
instancia de una clase que “recibirá” los eventos y nos permitirá reaccionar a ellos. A esto muchas
veces se le denomina “registrar un escuchador”.
Por ejemplo, en el código anterior, vamos a reaccionar al evento “click” de la ventana misma, de
forma de escribir algo en la consola cada vez que el usuario hace click con su mouse. Para esto, le
indicamos al componente (en este caso, la ventana) que estamos interesados en los eventos del
mouse, y le pasamos una instancia de una clase:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().addMouseListener(.........);
frame.setSize(400, 300);
frame.setVisible(true);
En este caso, en la línea 3 le estamos diciendo a la ventana que estamos interesados en responder a
los eventos producidos por el mouse (o sea, registrar un escuchador). En este caso, no se ha
especificado nada y se requiere reemplazar “……..” por una instancia que recibirá los eventos.
En este caso concreto, Swing define el método addMouseListener de esta forma:
Como se puede ver, Swing requiere que la instancia que reciba los eventos DEBE implementar la
interfaz especificada. Los diseñadores especificaron que esta interfaz tenga las siguientes
operaciones:
2.108
public interface MouseListener {
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
* @param e the event to be processed
*/
public void mouseClicked(MouseEvent e);
/**
* Invoked when a mouse button has been pressed on a component.
* @param e the event to be processed
*/
public void mousePressed(MouseEvent e);
/**
* Invoked when a mouse button has been released on a component.
* @param e the event to be processed
*/
public void mouseReleased(MouseEvent e); MouseListener
<<interface>>
/**
* Invoked when the mouse enters a component. + mouseClicked(MouseEvent e)
* @param e the event to be processed + mousePressed(MouseEvent e)
*/ + mouseReleased(MouseEvent e)
+ mouseEntered(MouseEvent e)
public void mouseEntered(MouseEvent e); + mouseExited(MouseEvent e)
/**
* Invoked when the mouse exits a component.
* @param e the event to be processed
*/
public void mouseExited(MouseEvent e);
}
De esta forma, los componentes sabrán qué métodos invocar cuando se produzcan los diferentes
eventos del mouse.
Desde el punto de vista nuestro, fácilmente podemos implementar las clases que recibirán los
eventos. Concretamente, en nuestro ejemplo, solo tenemos que crear una clase que implemente la
interfaz anterior:
2.109
class EventosDelMouse implements MouseListener{
@Override
public void mouseClicked(MouseEvent e){
System.out.println("Alguien hizo click!");
}
MouseListener
<<interface>>
@Override
public void mousePressed(MouseEvent e){
} + mouseClicked(MouseEvent e)
+ mousePressed(MouseEvent e)
+ mouseReleased(MouseEvent e)
@Override + mouseEntered(MouseEvent e)
public void mouseReleased(MouseEvent e){ + mouseExited(MouseEvent e)
}
@Override <<implements>>
public void mouseEntered(MouseEvent e){
} EventosDelMouse
@Override
public void mouseExited(MouseEvent e){
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
}
Como se puede ver, se ha definido una clase que implementa la interfaz. Esto significa que
TODAS las operaciones deben estar en la clase concreta. Después, se usa addMouseListener
para indicar que la instancia “escuchador” será la que responderá a los eventos del mouse de la
ventana.
2.110
En este ejemplo en particular, uno se puede preguntar qué pasa con el resto de los eventos. En
teoría, se puede reaccionar a otros eventos diferentes del “click” (botón presionado, botón liberado,
etc). De acuerdo a cómo está el código, Swing llamará a los métodos correspondientes cuando los
eventos suceden, pero no hay código en esos métodos, así que no sucederá nada.
Nótese que aun cuando no necesitemos reaccionar a otros eventos, la instancia que pasemos a
addMouseListener debe implementar todas las operaciones de la interfaz MouseListener . Si
no es así, entonces el código no compilará ya que técnicamente la clase no implementa
correctamente la interfaz:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().addMouseMotionListener(escuchadorMotion);
// <--
frame.setSize(400, 300);
frame.setVisible(true);
/**
* Invoked when a mouse button is pressed on a component and then
* dragged. {@code MOUSE_DRAGGED} events will continue to be
* delivered to the component where the drag originated until the
* mouse button is released (regardless of whether the mouse position
* is within the bounds of the component).
* <p>
* Due to platform-dependent Drag&Drop implementations,
* {@code MOUSE_DRAGGED} events may not be delivered during a native
* Drag&Drop operation.
* @param e the event to be processed
*/
public void mouseDragged(MouseEvent e);
/**
* Invoked when the mouse cursor has been moved onto a component
* but no buttons have been pushed.
* @param e the event to be processed MouseMotionListener
<<interface>>
*/
public void mouseMoved(MouseEvent e);
+ mouseDragged (MouseEvent e)
} + mouseMoved (MouseEvent e)
}
@Override
public void mouseMoved(MouseEvent e){
System.out.println("Mouse movido!");
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().addMouseListener(escuchador);
frame.getContentPane().addMouseMotionListener(escuchadorMotion);
frame.setSize(400, 300);
frame.setVisible(true);
}
}
En este caso, se han declarado dos clases diferentes, y de cada una se creó una instancia que
recibirá los mensajes desde Swing. Esto es totalmente válido y funciona.
Muchas veces, al crear clases que implementan interfaces, conviene recordar que una clase puede
realmente implementar varias interfaces en forma simultánea. Podemos refactorizar nuestro
ejemplo para demostrar esto:
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
2.113
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mouseDragged(MouseEvent e) {}
@Override
public void mouseMoved(MouseEvent e){
System.out.println("Mouse movido!");
}
}
MouseListener
<<interface>>
MouseMotionListener + mouseClicked(MouseEvent e)
<<interface>> + mousePressed(MouseEvent e)
+ mouseReleased(MouseEvent e)
+ mouseDragged (MouseEvent e) + mouseEntered(MouseEvent e)
+ mouseMoved (MouseEvent e) + mouseExited(MouseEvent e)
<<implements>>
<<implements>>
EventosDelMouse
2.114
public class Test{
public static void main(String[] args) {
JFrame frame = new JFrame("Ejemplo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
}
Desde el punto de vista de Swing, solo le interesa que la instancia que recibe implemente la
interfaz indicada. En este caso, como la clase (y por lo tanto la instancia) implementa ambas
interfaces, no hay problema en usarla como receptora de ambos tipos de eventos (Swing no se
confundirá al llamar a los métodos correspondientes cuando sucedan los eventos).
2.115
2.8. Arquitectura de una aplicación
2.8.1. Contratos
Estructura de un contrato
Operación Nombre de la operación y parámetros de entrada y salida
Descripción Breve descripción de la operación
Precondiciones Suposiciones relevantes sobre el estado del sistema o de los objeto
o conceptos del modelo de dominio antes de la ejecución de la
operación.
Son las condiciones que tiene que cumplir el sistema, no la lógica
de la aplicación
Si no existe o no se cumple la precondición, el contrato no es válido
(lanzar un error)
Postcondiciones Resultado esperado de la operación y estado de los objetos o
conceptos del dominio después de que se complete la operación.
Si solo se obtiene información, no hay post condición
Si se ingresa, actualiza o elimina información, si hay post
condición
Ejemplos de Contratos
Operación float sqrt(float número)
Descripción Calcula la raíz cuadrada de número
Precondiciones El valor del número debe ser mayor o igual a 0.
Postcondiciones El resultado de la operación contemplará un margen de error de a
lo mucho de un 0,1%.
sqr(número) implica que el resultado obtenido será un número
decimal mayor o igual a 0.
2.117
Contratos Tutores
Operación Calcular horas()
Ejemplo Calculadora
Se requiere implementar una calculadora con las 4 operaciones básicas.
Diagrama de
la Interfaz
2.119
Contratos en Java y su documentación
Calculadora
<<interface>>
+ sumar(int x, int y): int
+ restar(int x, int y): int
+ multiplicar(int x, int y): int
+ dividir(int x, int y): int
2.120
2.121
2.122
Implementación de los contratos
La implementación de los contratos, implica escribir una Clase, la cual
debe incluir como mínimo todos los sub-programas (métodos) que la
interface declara.
Cuando se trabaja con interfaces, se tiene concentrada en ella todas las
operaciones que nos interesa del sistema
Un contrato se debe implementar en un método de la interface.
2.123
Calculadora
<<interface>>
+ sumar(int x, int y): int
+ restar(int x, int y): int
+ multiplicar(int x, int y): int
+ dividir(int x, int y): int
<<implements>>
CalculadoraImpl
Calculadora
<<interface>>
public class Calculadora2Impl implements Calculadora{ + sumar(int x, int y): int
… + restar(int x, int y): int
} + multiplicar(int x, int y): int
+ dividir(int x, int y): int
<<implements>> <<implements>>
Calculadora2Impl CalculadoraImpl
2.124
Ejercicio
Dada la siguiente interfaz, realizar los contratos para cada una de las
operaciones.
Construir una clase que implemente las operaciones de la interfaz.
Diseñar el diagrama de clases.
<<interface>>
BancoUCN
/**
* Realiza el pago de una compra por parte del alumno
* Restricciones:
* Que el alumno exista.
* La clave debe ser la del alumno.
*
* @param rut del alumno.
* @param clave del alumno.
* @param monto a descontar del monedero del alumno.
* @return true si fue posible realizar la compra.
*/
boolean realizarCompra(String rut, String clave,
int monto);
}
2.127
Implementación de la interfaz
/**
* Clase que implementa el “como” funciona el sistema,
* a partir del “que”
* declarado por los contratos.
* @author Diego P. Urrutia <[email protected]>
* @version 2014.03.20
*/
/**
* @see BancoUCN#agregarAlumno
*/
public boolean agregarAlumno(String nombre,
String rut, String clave, int montoInicial) {
………
2.128
Diagrama de Clases
- $ MAX_MONTO =500
<<implements>>
1 ListaAlumnos * Alumno
- ListaAlumnos listaAlumno …
….
)
2.129
Uso de interfaces y contratos en el curso
Aun cuando normalmente toda clase tiene contratos que especifican las
operaciones de ésta, y las interfaces se pueden aplicar de muchas formas, en
el caso de este curso, será obligatorio cumplir los siguientes lineamientos:
1. Se definirá una clase “sistema”, con las operaciones necesarias para cumplir los
objetivos del problema que se requiere resolver
2. Las operaciones estarán definidas y documentadas en una interfaz
3. Las operaciones también estarán definidas en contratos, especificando pre,
postcondiciones.
4. Debido a lo anterior, la clase que implemente las operaciones tendrá por nombre
xxxxImpl, siendo xxxx el nombre de la interfaz que define las operaciones
import cl.ucn.ei.pa.paisciudades.dominio.Ciudad;
}
2.132
Formato general de la sentencia package es:
package paq1 [.paq 2[.paq 3]];
En JAVA, los paquetes son recipientes con clases, que se utilizan para
mantener el espacio de nombres de clase, dividido en compartimentos.
Por ejemplo, un paquete permite que se cree una clase llamada LISTA,
que se puede almacenar en un paquete propio, sin preocuparse por
conflictos con otra clase llamada LISTA, escrita por otra persona.
Paquete
por P
omisión
D. java
Paquetes:
Paquete por omisión.
Paquete P
Paquete R
.logica
Interface
pais.nombreOrganización.nombreProyecto
La clase que
implementa la
Todo en minúscula interface
Contenedores
App
.utils
Ejemplo:
Cualquier cosa que
cl.ucn.ei.pa.sistemaPaisesCiudades
no vaya en lógica
ni en dominio
Ejemplo 1
Se desea manejar la información de una cuenta bancaria de un banco. Una
cuenta tiene un saldo. Se puede depositar y girar sobre la cuenta bancaria.
La aplicación debe hacer un depósito sobre la cuenta y luego un giro sobre la
misma cuenta. Una vez hechas las transacciones sobre la cuenta, se debe
desplegar su saldo.
Contratos
CuentaBancaria
- int saldo
+ CuentaBancaria(int saldo)
+ girar(int montoGiro): boolean
+ depositar(int montoDeposito)
+ getSaldo(): int
+ setSaldo(int saldo)
+ toString(): String
2.137
Diagrama de clases
<<interface>>
SistemaCuentaBancaria
+ depositar(int montoDeposito)
+ girar(int montoGiro)
+ obtener DatosCuentaBancaria(): String
<<implements>>
1 CuentaBancaria
SistemaCuentaBancariaImpl
- CuentaBancaria cuentaBancaria - int saldo
+ CuentaBancaria(int saldo)
+ girar(int montoGiro):
boolean
+ depositar(
int montoDeposito)
+ getSaldo(): int
+ setSaldo(int saldo)
+ toString(): String
2.138
package cl.ucn.ei.pa.proyectocuentabancaria.dominio;
}
@Override
public String toString() {
return "CuentaBancaria [saldo=" + saldo + "]";
}
}//Fin CuentaBancaria
2.139
package cl.ucn.ei.pa.proyectocuentabancaria.logica;
/**
* @param montoDeposito: monto a depositar
*
* Descripción Se deposita dinero en la cuenta
* Precondiciones: Que exista la cuenta bancaria
* Postcondiciones: Saldo actualizado de la cuenta
*
*
*/
public boolean depositar (int montoDeposito);
/**
* @param montoGiro: monto a girar
* Descripción Se gira dinero desde la cuenta
* Precondiciones: Que exista la cuenta bancaria
* Postcondiciones: Saldo actualizado de la cuenta
*/
public boolean girar(int montoGiro);
/**
* @return un string con los datos de la cuenta bancaria
* Descripcion: Retorna los datos de la cuenta bnacraia
* Precondiciones: Que exista la cuenta bancaria
* Postcondiciones
*/
public String obtenerDatosCuentaBancaria();
}
2.140
package cl.ucn.ei.pa.proyectocuentabancaria.logica;
import cl.ucn.ei.pa.proyectocuentabancaria.dominio.CuentaBancaria;
public class SistemaCuentaBancariaImpl implements
SistemaCuentaBancaria{
private CuentaBancaria cuentaBancaria; ;
public SistemaCuentaBancariaImpl(int saldoInicial) {
this.cuentaBancaria = new CuentaBancaria(saldoInicial);
}
Cuando se levanta el sistema se crea el objeto cuenta
bancaria, es decir existe la cuenta
public boolean depositar(int montoDeposito){
if (cuentaBancaria==null){
throw new NullPointerException("Cuenta bancaria
no existe para hacer un deposito");
} Se trabaja con excepciones para implementar
las precondiciones indicadas en los contratos
Aquí se lanza la excepción
else{
return cuentaBancaria.depositar(montoDeposito);
}
}
public boolean girar(int montoGiro){
if (cuentaBancaria==null){
throw new NullPointerException("Cuenta bancaria
no existe para hacer un giro");
}
else{
return cuentaBancaria.girar(montoGiro);
}
Se trabaja con excepciones para implementar
}
las precondiciones indicadas en los contratos
Aquí se lanza la excepción
SistemaCuentaBancaria sistema =
new SistemaCuentaBancariaImpl(saldo);
try{
StdOut.println("Datos cuenta bancaria " +
sistema.obtenerDatosCuentaBancaria());
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
Se trabaja con excepciones para implementar
las precondiciones indicadas en los contratos
Aquí se está capturando la excepción
try {
sistema.depositar(74);
} catch(NullPointerException ex){
StdOut.println(ex.getMessage());
} La cantidad a girar o
try{ depositar debiera
sistema.girar(20); validarse en la App
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
2.142
}//Fin main
} //Fin App
Diagrama de objetos
Si se ingresa como saldo inicial el
valor 100 cuentaBancaria: CuentaBancaria
saldo = 100
174
154
Se imprime
Datos cuenta bancaria CuentaBancaria [saldo= 100]
Datos cuenta bancaria CuentaBancaria [saldo= 154]
Contratos
Operación Ingresar médico (rut, nombre,
regitro médico, especialidad) Nota
Descripción Se ingresa un médico La validación de los
datos de entrada
Precondiciones (cuando se lee) se hace
Postcondiciones Médico ingresado en la App.
Paciente
- String rut
- String nombre
- String diagnostico
- Medico medico
+ Paciente ()
+ setDiagnostico()
+ getMedico(): Medico
+ setMedico(Medico medico)
+ get y set....
+ toString(): String
Diagrama de clases <<interface>> 2.146
SistemaMedico
Los métodos de la
interfaz corresponden + ingresarMedico(String rut, String nombre,
a los contratos. String regitroMedico, String especialidad)
Un método por + ingresar Paciente(String rut, String nombre)
contrato + asociarDiagnostico(String diagnostico, String rut)
+ asociarMedico(String rutPaciente, String rutMedico)
+ obtenerDatosMedico(String rutMedico):String
+ obtenerDatosPacienteYSuMedico(String rutPaciente):String
<<implements>>
Medico
- String rut
- String nombre
- String registroMedico
1 - String especialidad
+ Medico()
+ get y set ….
+ toString();
1
SistemaMedicoImpl
Paciente
- Medico medico - String rut
- Paciente paciente 1 - String nombre
- String diagnostico
- Medico medico
+ Paciente ()
+ setDiagnostico()
+ getMedico(): Medico
+ setMedico(Medico medico)
+ get y set...
+ toString(): String
2.147
package cl.ucn.ei.pa.sistemamedico.dominio;
public class Medico {
private String rut;
private String nombre;
private String registroMedico;
private String especialidad;
public Medico(String rut, String nombre,
String registroMedico, String especialidad) {
this.rut = rut;
this.nombre = nombre;
this.registroMedico= registroMedico;
this.especialidad = especialidad;
}
public String getRut() {
return rut;
}
public void setRut(String rut) {
this.rut = rut;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getRegistroMedico() {
return registroMedico;
}
public void setRegistroMedico(String registroMedico) {
this.registroMedico = registroMedico;
}
public String getEspecialidad() {
return especialidad;
}
public void setEspecialidad(String especialidad) {
this.especialidad = especialidad;
}
@Override
public String toString() {
return "Medico [rut=" + rut + ", nombre=" + nombre +
", registroMedico=" + registroMedico + ",
especialidad="+ especialidad + "]";
}
}//Fin clase Medico
2.148
package cl.ucn.ei.pa.sistemamedico.dominio;
public class Paciente {
private String rut;
private String nombre;
private String diagnostico;
private Medico medico;
public Paciente(String rut, String nombre) {
this.rut = rut;
this.nombre = nombre;
this.diagnostico = null;
this.medico = null;
}
public String getRut() {
return rut;
}
public void setRut(String rut) {
this.rut = rut;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDiagnostico() {
return diagnostico;
}
public void setDiagnostico(String diagnostico) {
this.diagnostico = diagnostico; Esta versión de toString()
} tiene seleccionada la opción
public Medico getMedico() { del eclipse “saltar valores
return medico; nulos”
}
public void setMedico(Medico medico){ Cuando un objeto está
this.medico = medico; asociado con otro, es
} preferible sobrescribir el
@Override toString que se obtiene con el
public String toString() { Eclipse
return "Paciente [" + (rut != null ? "rut=" + rut +
", " : "")+ (nombre != null ? "nombre=" + nombre +
", " : "")+ (diagnostico != null ? "diagnostico=" +
diagnostico + ", " : "")+
(medico != null ? "medico=" + medico : "") + "]";
}
}//Fin Paciente
2.149
package cl.ucn.ei.pa.sistemamedico.logica;
import cl.ucn.ei.pa.sistemamedico.dominio.*;
package cl.ucn.ei.pa.sistemamedico.logica;
import cl.ucn.ei.pa.sistemamedico.dominio.*;
}
2.151
package cl.ucn.ei.pa.sistemamedico.logica;
import cl.ucn.ei.pa.sistemamedico.dominio.*;
import cl.ucn.ei.pa.sistemamedico.logica.SistemaMedico;
import cl.ucn.ei.pa.sistemamedico.logica.SistemaMedicoImpl;
import ucn.StdOut;
En la App se leen los datos (deben
validarse) y se despliegan resultados
La App representa la interfaz para el
ingreso y despliegue de los datos
public class App { (podría ser una interfaz gráfica)
sistema.ingresarMedico(rutMedico,nombre,
registroMedico,especialidad);
sistema.ingresarPaciente(rutPaciente, nombre);
try{
sistema.asociarDiagnostico("Apendicitis", rutPaciente);
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
Los objetos se crean en la clase que
implementa la interfaz
Se debe trabajar sin objetos en la App,
sino que con los datos primitivos
2.152
try {
sistema.asociarMedico(rutPaciente, rutMedico);
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
try{
String datosMedico = sistema.obtenerDatosMedico(rutMedico);
StdOut.println("Datos del medico: "+ datosMedico);
}catch( NullPointerException ex){
StdOut.println(ex.getMessage());
}
try{
String datosPaciente =
sistema.obtenerDatosPacienteySuMedico(rutPaciente);
StdOut.println("Datos del paciente: " +
datosPaciente);
}catch( NullPointerException ex){
StdOut.println(ex.getMessage());
}
}//Fin main
}//Fin App
Diagrama de Objetos
rut=111-k rut=222-1
registroMedico=151-5 diagnostico=Apendicitis
especialidad=cardiologo medico
Reglas
1. La validación de los datos de entrada se hace en la App
2. La lectura de los datos, los despliegues y la generación de archivos se hace en la
App
3. Los objetos se crean en la clase que implementa la interfaz
4. En un contenedor de objetos se ingresan objetos
5. En la App se trabaja con los datos primitivos, no con objetos
6. Se trabaja con excepciones para las precondiciones de los contratos
7. Si existe un requisito de desplegar ciertos datos, se debe tener un contrato que
obtenga esos datos, un String con todo lo requerido.
2.154
Ejemplo 3
Se necesita manejar información de un país y sus ciudades. Para un país
interesa saber su nombre, idioma y cantidad de habitantes. Para una ciudad,
su nombre, alcalde (suponga sólo 1 alcalde por ciudad) y cantidad de
habitantes. Se pide que haga un programa en Java que:
Ingrese el país Chile. Suponga que tiene 18.000.000 de habitantes.
Ingrese N ciudades de Chile, donde N se lee desde pantalla (lea desde
pantalla los datos de cada ciudad)
Una vez ingresada la información del país y sus ciudades, despliegue
todos los datos del país y los datos de cada una de sus ciudades.
Contratos
Operación Ingresar un país (nombre, idioma, cantidad habitantes pais)
Descripción Se ingresa un país
Precondiciones
Postcondiciones País creado
Versión 1
1
1 0 .. *
Pais Ciudad
- String nombre
- String nombre
- String idioma
- String alcalde
- int cantidadHabitantes
- int cantidadHabitantes
- Ciudad [ ] listaCiudades
- int cantidadCiudades + Ciudad(String nombre,
String alcalde,
+ Pais(String nombre, String idioma,
int cantidadHabitantes)
int cantidadHabitantes)
+ get y set …. + get y set….
+ getCantidadCiudades(): int + toString():String
+ getCiudadI(int i): Ciudad
+insertarCiudad(Ciudad ciudad):boolean
+ toString(): String
2.157
package cl.ucn.ei.pa.paisciudades.dominio;
package cl.ucn.ei.pa.paisciudades.dominio;
public class Pais {
private String nombre;
private String idioma;
private int cantidadHabitantes;
private Ciudad [] listaCiudades;
private int cantidadCiudades;
private int max;
public Pais(String nombre, String idioma,
int cantidadHabitantes, int max) {
this.nombre = nombre;
this.idioma = idioma;
this.cantidadHabitantes = cantidadHabitantes;
listaCiudades = new Ciudad[max];
cantidadCiudades = 0;
this.max = max;
}
public final String getNombre() {
return nombre;
}
public final void setNombre(String nombre) {
this.nombre = nombre;
}
public final String getIdioma() {
return idioma;
}
2.159
return salida;
}
}
package cl.ucn.ei.pa.paisciudades.logica;
import cl.ucn.ei.pa.paisciudades.dominio.Pais;
}
2.161
package cl.ucn.ei.pa.paisciudades.logica;
import cl.ucn.ei.pa.paisciudades.dominio.*;
public class SistemaPaisCiudadesImpl implements
SistemaPaisCiudades {
private Pais pais;
public SistemaPaisCiudadesImpl() {
pais = null;
}
}
2.162
package cl.ucn.ei.pa.paisciudades.logica;
import ucn.StdOut;
import ucn.StdIn;
import cl.ucn.ei.pa.paisciudades.dominio.*;
public class App {
public static void
LeerCiudadesPais(SistemaPaisCiudades sistema){
StdOut.print("Cantidad de ciudades de Chile: ");
int N = StdIn.readInt();
sistema.ingresarPais("Chile","Espanol",18000000,N);
for (int i = 1; i <= N; i++) {
StdOut.print("Ingrese nombre ciudad: ");
String nombreCiudad = StdIn.readString();
StdOut.print("Ingrese Alcalde: ");
String alcalde = StdIn.readString();
StdOut.print("Ingrese cantidad habitantes: ");
int cantidadHabitantes = StdIn.readInt();
try { Que no exista espacio, no es una precondición en un contrato
boolean ingreso =
sistema.ingresarCiudadDeUnPais("Chile",
nombreCiudad, alcalde, cantidadHabitantes);
if (!ingreso){
StdOut.println("No hay espacio para ingresar ciudades");
}
} catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}
}
}
public static void main(String[] args) {
SistemaPaisCiudades sistema = new
SistemaPaisCiudadesImpl();
LeerCiudadesPais(sistema);
try {
StdOut.println(sistema.
obtenerDatosPaisCiudades("Chile"));
} catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}
}//Fin main
}//Fin App
2.163
Diagrama de objetos
c: Ciudad
nombre= Santiago
alcalde= Alessandri
cantidadHabitantes= 6000000
p: Pais
c: Ciudad
nombre = Chile
nombre= Antofagasta
idioma=Español
cantidadHabitantes=18000000 alcalde= Rojo
cantidadHabitantes= 400000
listaCiudades
cantCiudades= 3 c: Ciudad
nombre= Concepcion
alcalde= Ortiz
cantidadHabitantes= 1000000
2.164
Versión 2
Diagrama de clases del dominio de la aplicación
Pais
Ciudad
- String nombre - String nombre
- String idioma - String alcalde
- int cantidadHabitantes - int cantidadHabitantes
- ListaCiudades listaCiudades + Ciudad(String nombre,
String alcalde,
+ Pais(String nombre, String idioma, int cantidadHabitantes)
+ get y set()….
int cantidadHabitantes) + get y set()…
+ toString(): String + toString(): String
+ getListaCiudades(): ListaCiudades
*
+ ingresarCiudad(Ciudad c): boolean
1
<<interface>>
SistemaPaisCiudades
SistemaPaisCiudadesImpl + ingresarPaisCiudades(nombre,
idioma, cantidadhabitantes)
- Pais p + ingresarCiudadDeUnPais (
nombrePais, nombreCiudad,
alcalde, cantidadHabitantes)
+ obtenerDatosPaisCiudades (
nombrePais): String
1
Ciudad
Pais - String nombre
- String alcalde
- String nombre - int cantidadHabitantes
- String idioma + Ciudad(String nombre,
- int cantidadHabitantes String alcalde,
- ListaCiudades listaCiudades int cantidadHabitantes)
+ get y set()…
+ Pais(String nombre, String idioma,
int cantidadHabitantes) + toString(): String
+ get y set()….
+ toString(): String *
+ getListaCiudades(): ListaCiudades
1
+ ingresarCiudad(Ciudad c): boolean
ListaCiudades
- Ciudad [] lc
- int cantidadCiudades
- int max
+ ListaCiudades(int max)
+ getCantidadCiudades(): int
+ insertarCiudad(Ciudad ciudad): boolean
+ getCiudad (int i): Ciudad
+ toString(): String
2.166
package cl.ucn.ei.pa.paisciudades.dominio;
package cl.ucn.ei.pa.paisciudades.logica;
import cl.ucn.ei.pa.paisciudades.dominio.Ciudad;
public class ListaCiudades {
private Ciudad[] lc;
private int cantidadCiudades;
private int max;
public ListaCiudades(int max) {
lc = new Ciudad[max];
cantidadCiudades = 0;
this.max = max;
}
public int getCantidadCiudades() {
return cantidadCiudades;
}
public void setCantidadCiudades(int cantidadCiudades){
this.cantidadCiudades = cantidadCiudades;
}
public boolean insertarCiudad(Ciudad ciudad) {
if (cantidadCiudades < max) {
lc[cantidadCiudades] = ciudad;
cantidadCiudades++;
return true;
} else {
return false;
}
}
public Ciudad getCiudad (int i) {
if (i >= 0 && i < cantidadCiudades) {
return lc[i];
} else {
return null; Para imprimir el contenedor, es mejor construir
} el método toString en vez del que se obtiene con
} Eclipse o NetBeans. La idea es ir obteniendo
@Override elemento por elemento del contendor
public String toString(){
return "ListaCiudades [" + (lc != null ? "lc=" +
Arrays.toString(lc) + ", " : "") +
"cantidadCiudades="+ cantidadCiudades + ", max=" +
max + "]";
}
}//Fin ListaCiudades
2.169
package cl.ucn.ei.pa.paisciudades.logica;
package cl.ucn.ei.pa.paisciudades.logica;
import cl.ucn.ei.pa.paisciudades.dominio.*;
public SistemaPaisCiudadesImpl() {
pais = null;
}
this.pais=new Pais(nombre,idioma,
cantidadHabitantes,cantidadCiudades);
}
2.170
return ingreso;
}
else{
throw new NullPointerException ("No existe pais");
}
}
package cl.ucn.ei.pa.paisciudades.logica;
import ucn.StdOut;
import ucn.StdIn;
import cl.ucn.ei.pa.paisciudades.dominio.*;
import cl.ucn.ei.pa.paisciudades.logica.SistemaPaisCiudades;
import cl.ucn.ei.pa.paisciudades.logica.SistemaPaisCiudadesImpl;
public class App {
public static void LeerCiudadesPais(
SistemaPaisCiudades sistema) {
StdOut.print("Ingrese cantidad ciudades Chile: ");
int N = StdIn.readInt();
sistema.ingresarPais("Chile","Espanol",17000000, N);
for (int i = 1; i <= N ; i++) {
StdOut.print("Ingrese nombre ciudad: ");
String nombre = StdIn.readString();
StdOut.print("Ingrese Alcalde: ");
String alcalde = StdIn.readString();
StdOut.print("Ingrese cantidad habitantes: ");
int cantidad = StdIn.readInt();
try {
boolean ingreso =
sistema.ingresarCiudadDeUnPais("Chile",
nombre, alcalde, cantidad);
if(!ingreso){
StdOut.println("No se ingreso ciudad.
No hay espacio");
}
catch NullPointerException ex) {
StdOut.println(ex.getMessage());
}
}
}
2.172
try {
StdOut.println(
sistema.obtenerDatosPaisCiudades("Chile"));
} catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}
}//Fin main
}//Fin App
2.173
Ejemplo 4
Precondiciones
Precondiciones
Postcondiciones
1
Pais Ciudad
- String nombre - String nombre
- int cantidadHabitantes - int cantidadUniversidades
- String idioma - int cantidadMuseos
- String continente - Pais pais
- ListaCiudades listaCiudades + Ciudad()
+ Pais(String nombre, int cantidadHabitantes, + get y set …
String idioma, String continente) + setPais()
+ get y set…
+ getListaCiudades(): ListaCiudades
+ getPais(): Pais
+ toString():String + toString(): String
+ ingresarCiudad(Ciudad ciudad)
*
* Recuerde que la responsabilidad de
ingresar la ciudad como ciudad del país es
del país
1
ListaPaises ListaCiudades
- Pais [] lp
- int cantidadPaises
- Ciudad [] lc
- int max - int cantidadCiudades
- int max
+ ListaPaises(int max) + ListaCiudades(int max)
+ ingresarPais(Pais pais): boolean + ingresarCiudad(
+ buscarPais(String nombre): Pais Ciudad ciudad):boolean
+ getCantidadPaises(): int + buscarCiudad(String nombre):
+ getPais (int i): Pais Ciudad
+ toString():String + getCantidadCiudades():int
+ getCiudad (int i): Ciudad
+ toString():String
2.177
Diagrama de clases <<interface>>
SistemaPaisesCiudades
<<implements>>
+ ingresarPais(nombre, habitantes, idioma,
SistemaPaisesCiudadesImpl Continente, cantidadCiudades): boolean
+ingresarCiudad(nombre, universidades, museos):boolean
+asociarPaisCiudad(nombrePais, nombreCiudad)
- ListaPaises listaPaises
+ encontrarCiudadesPais(nomPais):String
- ListaCiudades listaCiudades + obtenerCantidadPaisesEuropeos():int
+ obtenerDatosPaisMasHabitantes(): String
+encontrarPaisDeUnaCiudad(nomCiudad):String
1
Pais Ciudad
- String nombre
- String nombre
- int cantidadUniversidades
- int cantidadHabitantes
- int cantidadMuseos
- String idioma
- Pais pais
- String continente
+ Ciudad(String nombre,
- ListaCiudades listaCiudades int cantidadUniversidades,
+ Pais(String nombre, int cantidadHabitantes, int cantidadMuseos)
String idioma, String continente) + get y set …
+ get y set… + setPais(Pais pais)
+ getListaCiudades(): ListaCiudades + getPais(): Pais
+ toString():String + toString():String
+ ingresarCiudad(Ciudad ciudad)
*
*
1 1
ListaPaises
- Pais [] lp ListaCiudades
- int cantidadPaises - Ciudad [] lc
-int max - int cantidadCiudades
+ ListaPaises(int max) - int max
+ ingresarPais(Pais pais): boolean + ListaCiudades(int max)
+ buscarPais(String nombre): Pais + ingresarCiudad(
+ getCantidadPaises(): int Ciudad ciudad):boolean
+ getPais (int i): Pais + buscarCiudad(String nombre):
Ciudad
+ toString():String + getCantidadCiudades():int
+ getCiudad (int i): Ciudad
+ toString():String
1
2.178
package cl.ucn.ei.pa.sistemapaisesciudades.dominio;
//@Override
public String toString() {
return "Ciudad [" + (nombre != null ? "nombre=" + nombre +
", " : "") +
"cantidadUniversidades="+ cantidadUniversidades +
", cantidadMuseos=" + cantidadMuseos + "]";
}
package cl.ucn.ei.pa.sistemapaisesciudades.dominio;
import cl.ucn.ei.pa.sistemapaisesciudades.logica.ListaCiudades;
package cl.ucn.ei.pa.sistemapaisesciudades.logica;
import cl.ucn.ei.pa.sistemapaisesciudades.dominio.Ciudad;
}
2.183
package cl.ucn.ei.pa.sistemapaisesciudades.logica;
import cl.ucn.ei.pa.sistemapaisesciudades.dominio.Pais;
package cl.ucn.ei.pa.sistemapaisesciudades.logica;
import cl.ucn.ei.pa.sistemapaisesciudades.dominio.*;
package cl.ucn.ei.pa.sistemapaisesciudades.logica;
import ucn.StdOut;
import ucn.StdIn;
import cl.ucn.ei.pa.sistemapaisesciudades.logica.SistemaPaisesCiudades;
import cl.ucn.ei.pa.sistemapaisesciudades.logica.SistemaPaisesCiudadesImpl;
LeerPaisesCiudades(sistema, cantidadPaises);
try{
StdOut.println("Pais " +
sistema.encontrarPaisDeUnaCiudad(nombreCiudad));
} catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}
ingreso = sistema.ingresarCiudad(nombreCiudad,
cantidadUniversidades, cantidadMuseos);
//Se ingresa la ciudad a la lista de todas
//las ciudades
if (!ingreso){
StdOut.println("No se ingreso la ciudad.
No hay espacio");
}
else{
try{
sistema.asociarPaisCiudad(nombrePais,
nombreCiudad);
//Se asocia el pais y la ciudad
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
}
}
}
}
}
}
2.190
Si los datos se leen de la siguiente forma:
1°. Cantidad de países, cantidad de ciudades
2°. Por cada país los datos del país
3°. Por cada ciudad, los datos de la ciudad, incluyendo el nombre del pais
al que pertenece
Los contratos ingresarCiudad y asociarPaisCiudad, asociados al ingreso de
los datos serían reemplazados por los siguientes:
Parte de la App
public static void main(String[] args) {
StdOut.print("Ingrese cantidad de paises: ");
int cantidadPaises = StdIn.readInt();
StdOut.print("Ingrese cantidad de ciudades: ");
int cantidadCiudades = StdIn.readInt();
SistemaPaisesCiudades sistema =
new SistemaPaisesCiudadesImpl(cantidadPaises,
cantidadCiudades);
LeerPaises(sistema, cantidadPaises);
LeerCiudades(sistema, cantidadCiudades);
……
2.193
Persona
Empleado Estudiante
2.9.1. Concepto
Se permite definir una nueva clase B, como una extensión de una clase previa A.
B se denomina subclase de A y A se denomina superclase de B
B es la Clase derivada y A es la Clase base
Una subclase típicamente aumenta o redefine la estructura existente y el
comportamiento de su superclase.
Ejemplos:
Figura
Cuenta Bancaria
Persona
Estudiante Empleado
Persona
Variables de instancia:
- nombre
- direccion
- fechaNacimiento
- rut
Métodos:
- inicializarDatosPersona
- obtenerDatosPersona
Estudiante Empleado
Variables de instancia: Variables de instancia:
- numeroMatricula
- sueldo
- carrera
Métodos: Métodos:
- InicializarDatosEstudiante - IncializarDatosEmpleado
- obtenerCarrera - obtenerSueldo
- obtenerNumeroMatricula
2.197
Herencia de propiedades en una jerarquía de clases
Estudiante Estudiante
Variables de instancia: Variables de instancia:
- numeroMatricula - numeroMatricula
- carrera - carrera
Métodos: - rut
- inicializarDatosEstudiante - nombre
- obtenerCarrera - dirección
- obtenerNumeroMatricula - fechaNacimiento
+ Métodos:
- inicializarDatosEstudiante
Persona - obtenerCarrera
- obtenerNumeroMatricula
- inicializarDatosPersona
- obtenerDatosPersona
Empleado Empleado
Variables de instancia: Variables de instancia:
- sueldo - sueldo
Métodos: -rut
- inicializarDatosEmpleado - nombre
- obtenerSueldo - dirección
+ - fechaNacimiento
Métodos:
Persona - inicializarDatosEmpleado
- obtenerSueldo
- inicializarDatosPersona
- obtenerDstosPersona
+
La habilidad de un lenguaje para soportar la herencia,
Persona distingue a los
lenguajes orientados al objeto, de los lenguajes basados en objetos.
De esta manera, todas las clases son subclases directas o indirectas de la clase Object.
2.200
Notación
La representación de la herencia, de acuerdo a la notación utilizada por
UML (Unified Modeled Language - Lenguaje de Modelado Unificado)
Superclase
Subclase1 Subclase2
Ejemplos:
Cuenta
Bancaria
Cuenta Cuenta
Ahorro Corriente
2.201
Equipo
Intercambiador
Bomba Estanque
de Calor
Estanque Estanque
.......
Esférico a Presión
Figura
Cuadrado
2.202
Mensajes a super
Ejemplo
A public class A {
- int dato private int dato;
+ A(int dato) public A(int dato) {
+ m1(int x): int this.dato = dato;
+ get y set()… }
public int getDato() {
StdOut.println("Pasa por getDato() del padre");
B return dato;
- int dato }
public void setDato(int dato) {
+ B(int dato, int dato1) this.dato = dato;
}
+ m1(int dato): int public int m1(int x) {
+ m2(): int StdOut.println("Pasa por m1 del padre");
+ get y set()… return x + 5;
}
}
2.203
Se imprime
b
Pasa por m1 del padre
a.m1(5)= 10
Pasa por m1 del hijo
Pasa por m1 del padre
b.m1(2)= 7
Pasa por m2
Pasa por m1 del padre
Pasa por getDato() del padre
b.m2()= 11
2.204
Ejemplo: Se define la subclase Punto3D, que utiliza el constructor super para
inicializar las variables x e y, después imprime el punto en 3D resultante.
public class Punto {
private int x;
private int y;
public Punto(int x, int y){ Recuerde que los atributos de la
this.x = x;
super clase se colocan privados,
this.y = y;
} ya que para eso se tienen los
public int getX(){ métodos get y set asociados . Los
return x; métodos pudieran ser protegidos
}
public int getY(){
return y;
}
}
x = 10 y = 20 z = 30
p = Punto3D @ 1cc807
Resultado: Clase del Dirección
Objeto
2.205
Ejemplo
La clase Punto3D hereda de su superclase Punto la implementación del
método de la distancia para puntos en 2D. Necesita por lo tanto sobrescribir
esa definición con una nueva para puntos en 3D.
En la clase Punto3D hay sobrecarga de la distancia en 3D y hay redefinición
(sobrescritura) de la distancia en 2D. Si hay distintas versiones de un
public class Punto { método, se deben colocar todas en
private int x; Redefinición el diagrama de clases.
private int y; Los métodos en el diagrama de
clases deben llevar los parámetros
public Punto(int x, int y){
this.x=x;
this.y=y;
}
public int getX(){ Punto
return x;
} - int x
public int getY(){ - int y
return y;
} + Punto(int x, int y)
public double distancia + getX(): int
(int x, int y){ + getY(): int
StdOut.println("Primer método + distancia(int x, int y):double
distancia del padre Punto. + distancia (Punto p): double
Parametros: x,y");
int dx = this.x - x;
int dy = this.y - y;
return Math.sqrt(dx*dx + dy*dy); Punto3D
} - int z
public double distancia(Punto p){
System.out.println("Segundo + Punto3D (int x, int y, int z)
metodo distancia del padre + getZ():
Se imprime int
Pasa por m1 del padre
Punto. Parametros: Punto"); + distancia(int x, int y, int z):
a.m1(5)= 10
return this.distancia(p.x, p.y); Pasa por m1 del hijo double
} Pasa por m1 del padre
+ distancia(Punto3D otro):
b.m1(2)= 7
Si el objeto que invoca es de la clase Punto, se invoca el Pasa por m2 double
primer método de distancia de la clase Punto. Pasa por m1 del padre
Si el objeto que invoca es de la clase Punto3D, se invoca + distancia(int
Pasa por getDato()x,del
intpadre
y): double
b.m2()= 11
el tercer método de distancia de la clase Punto3D
}//Fin clase Punto Redefinición
2.206
public class Punto3D extends Punto{
private int z;
int dx = this.getX() - x;
//Se tiene que usar el getX(), porque es private
int dy = this.getY() - y;
int dz = this.z - z;
return Math.sqrt(dx*dx + dy*dy + dz*dz);
}
}
2.207
public class Punto3DDist {
public static void main(String[] args) {
Punto3D p1 = new Punto3D(30, 40, 10);
Punto3D p2 = new Punto3D(0, 0, 0);
Punto p = new Punto(4, 6);
p2: Punto3D p: Punto p1: Punto3D
x=0 x=4 x = 30
y=0 y=6 y = 40
z=0 z = 10
StdOut.println("p1 = " + p1.getX() + ", " + p1.getY() +
", " + p1.getZ());
StdOut.println("p2 = " + p2.getX() + ", " + p2.getY() +
", " + p2.getZ());
StdOut.println("p = " + p.getX() + ", " + p.getY());
StdOut.println("------------------------------");
StdOut.println("p1.distancia(p2) = " + p1.distancia(p2));
StdOut.println("------------------------------");
StdOut.println("p1.distancia(4, 6)=" + p1.distancia(4,6));
StdOut.println("------------------------------");
StdOut.println("p1.distancia(p) = " + p1.distancia(p));
}
}
Se imprime
p1 = 30, 40, 10
p2 = 0, 0, 0
p = 4, 6
------------------------------
Segundo metodo distancia del hijo Punto3D. Parametros:
Punto3D
Primer metodo distancia del hijo Punto3D. Parametros: x, y, z
p1.distancia(p2) = 50.99019513592785
------------------------------
Tercer metodo distancia del hijo Punto3D. Parametros: x, y
p1.distancia(4, 6) = 2.23606797749979
------------------------------
Segundo metodo distancia del padre Punto. Parametros: Punto
Tercer metodo distancia del hijo Punto3D. Parametros: x, y
p1.distancia(p) = 2.23606797749979
2.208
Notas:
Hay una tensión importante, entre la herencia y el encapsulamiento.
Ejemplo:
Se desea construir una aplicación que manipula círculos, triángulos y rectángulos en
un sistema gráfico, en base a las siguientes operaciones:
Indicar ubicación de un círculo, de un triángulo y de un rectángulo.
Dibujar un círculo, un triángiulo y un rectángulo.
Imprimir un círculo, un triángiulo y un rectángulo.
Rotar un círculo, un triángiulo y un rectángulo.
Indicar el color de un círculo, un triángulo y un rectángulo.
Figura
Debe hacerse notar, que las clases Rectángulo, Triángulo y Círculo, sobrescriben los
procedimientos Dibujar, Imprimir y Rotar, los que son específicos para cada una de
las clases. En esta solución, según sea el tipo de la información que se está
procesando, se ejecuta el procedimiento adecuado para la situación que se presenta;
por ejemplo, si el método Rotar se aplica a un objeto de la clase Rectángulo, el método
asociado a esa clase es ejecutado.
Para extender o reusar el sistema, basta con crear una nueva subclase dentro de la
jerarquía de clases mostrada anteriormente, que agregue o modifique propiedades
de la superclase, sin necesidad de modificar las clases existentes.
2.210
Por ejemplo, si se desea incorporar la clase Cuadrado al sistema, sólo se modifica
la definición de clases anterior.
Figura
Rotar
Cuadrado Dibujar
Concepto de polimorfismo
Cuando se aplica un método a un objeto, el tipo del objeto se comprueba
durante la compilación, para asegurarse de que el método llamado existe en
la clase declarada.
Ejemplo: Dos clases tienen una relación subclase/superclase, con un único método
que se sobrescribe en la subclase
A
Se imprime
p2 = 0, 0, 0
p4 = 40, 50
p5 = 40, 50, 60
------------------------------
Segundo metodo distancia del padre (Punto). Parametros: Punto
Tercer metodo distancia del hijo Punto3D. Parametros: x, y
p4.distancia(p2) = 1.0671873729054748
------------------------------
Segundo metodo distancia del hijo Punto3D. Parametros: Punto3D
Primer metodo distancia del hijo Punto3D. Parametros: x, y, z
p5.distancia(p2) = 87.74964387392122
------------------------------
Primer metodo distancia del hijo Punto3D. Parametros: x, y, z
p5.distancia(1,1,2) = 85.3580693314932
------------------------------
2.213
2.9.3. Clase abstracta
Volvamos al ejemplo de las figuras
Figura
Variables de instancia: Clase abstracta
Centro
Color
Métodos:
Ubicar
Dibujar
Métodos
Imprimir
abtractos
Rotar
Color
Figura
<<abstracta>>
La clase Figura debe tener como abstractos los métodos rotar, dibujar e
imprimir. Lo anterior tiene la finalidad de que el chequeo en tiempo de
compilación sea exitoso cuando se invoca un método para un objeto de una de
las subclases de Figura.
Por lo tanto, cuando se deba crear (new) una figura lo que realmente se hará
es crear un círculo o un triángulo o un rectángulo. De esta forma, cuando se
invoque un método como rotar para un círculo, se ejecute el rotar del círculo.
Lo mismo con los métodos imprimir y dibujar. Esto significa que nuca
haremos new Figura()
2.214
A) Conceptos
Algunas de las clases tendrán instancias, otras no.
La clase que no tienen instancias, se denomina clases abstractas.
Una clase abstracta es escrita con el propósito de que sus subclases le
agreguen estructura y comportamiento, a través de completar la
implementación de sus (usualmente) métodos incompletos.
No se pueden crear instancias de dichas clases directamente, con el
operador new.
Clase abstracta
Es una clase que nunca es instanciada. Contiene los métodos comunes a
todas las subclases.
Es usada como una base, a partir de la cual, otras clases pueden heredar.
Método Abstracto
Es un método cuya implementación no es definida en la declaración de la
clase en que aparece. Su definición se hace en una clase descendente.
2.215
Ejemplo: Se tiene una clase con un método abstracto, seguida de una
clase que implementa ese método.
Resultado
Inside B’s callme method
Inside A’s metoo method
2.216
Modificador final, para calificar una variable, método o clase
final asociado a un método, indica que este no puede ser sobrescrito por
las subclases.
final, usado como modificador de una clase, indica que la clase no puede
tener subclases.
/*
NO COMPILA. El método sumar está
public int sumar() { declarado como final en la superclase
return a1*a2; ClaseA, superclase de la clase ClaseB
}
*/
}
NO COMPILA. La
public class ClaseC extends ClaseB{
clase ClaseB está
private int c1;
definida como final
public ClaseC(int a1, int a2, int b1, int c1) {
super(a1, a2, b1);
this.c1 = c1;
}
public int getC1() {
return c1;
}
public void setC1(int c1) {
this.c1 = c1;
}
}
2.219
Resumen de los atributos que pueden tener variables y métodos
VARIABLE:
{final}
{static}
MÉTODO:
{final / abstract}
{static}
Contratos
Operación depositar (monto depósito) Recuerde que el
chequeo del monto
Descripción Se deposita dinero en la cuenta corriente y del depósito > 0 es
en la cuenta de ahorro
validación del dato de
Precondiciones Que exista la cuenta corriente entrada. Se hace en
Que exista la cuenta de ahorro la App
Postcondiciones Saldo actualizado de la cuenta corriente Por lo tanto no va en
Saldo actualizado de la cuenta de ahorro el contrato
2.221
CuentaBancaria
- double $ tasaInteres
- int saldo
+ CuentaBancaria(int saldi)
+ $ getTasaInteres(): double
+ $ setTasaInteres(double tasaInteres)
+ depositar(int montoDeposito)
+ girar(int montoGiro): boolean
+ getSaldo(): int
+ setSaldo(int saldo)
+ toString(): String
CuentaCorriente CuentaAhorro
- int $ corrNumero - int $ corrNumero
- int numeroCuenta - int numeroCuenta
+ CuentaCorriente(int saldo) + CuentaAhorro(int saldo)
+ get y set NumeroCuenta()… + get y set NumeroCuenta()…
+ $ getCorrNumero(): int + $ getCorrNumero(): int
+ $ setCorrNumero(int corrNumero) + $ setCorrNumero(int corrNumero)
+ agregarInteres() + descontarMantencion()
+ toString(): String + toString(): String
CuentaCorriente CuentaAhorro
- int $ corrNumero - int $ corrNumero
- int numeroCuenta - int numeroCuenta
+ CuentaCorriente(int saldo) + CuentaAhorro(int saldo)
+ get y set NumeroCuenta()… + get y set NumeroCuenta()…
+ $ getCorrNumero(): int + $ getCorrNumero(): int
+ $ setCorrNumero(int corrNumero) + $ setCorrNumero(int corrNumero)
+ agregarInteres() + descontarMantencion()
+ toString(): String + toString(): String
1 1
SistemaCuentaCorrienteCuentaAhorroImpl
- CuentaCorriente cuentaCorriente
- CuentaAhoro cuentaAhorro
<<implements>>
SistemaCuentaCorrienteCuentaAhorro
<<interface>>
+ chequearTasaInteres(tasaInteres)
+ obtenerDatosCuentaCorriente(): String
+ obtenerDatosCuentaAhorro(): String
+ depositar(monto)
+ descontarMantencion()
+ agregarInteres(tasaInteres)
2.224
package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio;
@Override
public String toString() {
return "CuentaBancaria [saldo=" + saldo + "]";
}
}
package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio;
@Override
public String toString() {
return "CuentaAhorro [numeroCuenta=" + numeroCuenta +
", saldo=" + getSaldo() + "]";
}
}
package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio;
@Override
public String toString() {
return "CuentaCorriente [numeroCuenta=" + numeroCuenta +
", saldo= "+ getSaldo()+"]" ;
}
}
package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.logica;
}
2.228
package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.logica;
import cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio.*;
public SistemaCuentaCorrienteCuentaAhorroImpl(){
//Cuando se levanta el sistema, se crean las
//2 cuentas con un saldo 0
cuentaAhorro = new CuentaAhorro(0);
cuentaCorriente = new CuentaCorriente(0);
}
package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.logica;
import ucn.StdIn;
import ucn.StdOut;
SistemaCuentaCorrienteCuentaAhorro sistema =
new SistemaCuentaCorrienteCuentaAhorroImpl();
try{
StdOut.println("datos cuenta corriente: + " +
sistema.obtenerDatosCuentaCorriente());
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
StdOut.println();
try{
StdOut.println("datos cuenta ahorro: + " +
sistema.obtenerDatosCuentaAhorro());
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
StdOut.println();
2.231
}
2.232
Concepto de Casteo A
- int a1
+ A(int a1)
+ m1()
B C
- int b1 - int c1
+ A(int a1, int b1) + A(int a1, int c1)
+ m2() + m3()
Entre los vehículos es posible distinguir los autos y las camionetas. Para los
autos se tiene además, la lectura del cuenta kilómetros y la capacidad del
estanque de combustible. Para las camionetas se tiene además, su capacidad
de carga.
Se pide:
Modelo del dominio
Contratos
Diagrama de clases del dominio de la aplicación
Diagrama de clases
Código Java
2.234
Modelo del dominio
Auto Camioneta
Patente Patente
Marca Marca
Año
Año
Lectura cuenta kilómetros
Capacidad estanque combustible Capacidad de carga
Contratos
Operación Ingresar camioneta (patente, marca, año, capacidad carga)
Descripción Se ingresa una camioneta a la lista general de vehículos
Precondiciones
Postcondiciones Camioneta ingresada a la lista general de vehículos
10
Camioneta Auto
- int capacidadCarga - int kilometraje
+ Camioneta(String patente,
- int capacidadEstanque
+ Auto(String patente, String marca,
String marca, int agno, int agno, int kilomeraje,
int capacidadCarga) int capacidadEstanque)
+get y set ... + get y set ….
+ costoReparacion(): int + costoReparacion(): int
+ toString(): String + toString(): String
1 Camioneta Auto
- int capacidadCarga - int kilometraje
+ Camioneta(String patente,
- int capacidadEstanque
+ Auto(String patente, String marca,
String marca, int agno, int agno, int kilomeraje,
int capacidadCarga) int capacidadEstanque)
+get y set ... + get y set ….
+ costoReparacion(): int + costoReparacion(): int
+ toString(): String + toString(): String
SistemaVehiculos
<<interface>>
+ingresarAuto(): boolean
+ingresarCamioneta(): boolean
+obtenerDatosVehiculos(): String
+obtenerDatosVehiculo (): String
+obtenerTotalAutos(): int
+obtenerTotalCamionetas(): int
+obtenerTotalVehiculos(): int
+obtenerDatosCamionetaMasCarga(): String
<<implements>>
SistemaVehiculosImpl
ListaVehiculos listaVehiculos
2.238
package cl.ucn.ei.pa.sistemavehiculos.dominio;
@Override
public String toString() {
return "Vehiculo [" + (patente != null ?
"patente=" + patente + ", " : "")+
(marca != null ? "marca=" + marca + ", " : "")+
"agno=" + agno + "]";
}
}
2.239
package cl.ucn.ei.pa.sistemavehiculos.dominio;
public class Auto extends Vehiculo{
private int kilometraje;
private int capacidadEstanque;
public Auto(String patente, String marca, int agno,
int kilometraje, int capacidadEstanque) {
super(patente , marca , agno);
this.capacidadEstanque = capacidadEstanque;
this.kilometraje=kilometraje;
}
public int getKilometraje() {
return kilometraje;
}
public int getCapacidadEstanque() {
return capacidadEstanque;
}
public int costoReparacion () {
return (capacidadEstanque * 20000);
}
@Override
public String toString() {
return "patente: "+ getPatente() + " marca: "+
getMarca()+ " agno: " + getAgno()+ " " +
"Auto [kilometraje=" + kilometraje +
", capacidadEstanque=" + capacidadEstanque + "]";
}
}
2.240
package cl.ucn.ei.pa.sistemavehiculos.dominio;
public class Camioneta extends Vehiculo{
private int capacidadCarga;
public Camioneta (String patente, String marca,
int agno, int capacidadCarga) {
super(patente, marca, agno);
this.capacidadCarga = capacidadCarga;
}
@Override
public String toString() {
return "patente: "+ getPatente() + " marca: "+
getMarca()+ " agno: " + getAgno()+ " Camioneta
[capacidadCarga=" + capacidadCarga + "]";
}
}
2.241
package cl.ucn.ei.pa.sistemavehiculos.logica;
import cl.ucn.ei.pa.sistemavehiculos.dominio.Auto;
import cl.ucn.ei.pa.sistemavehiculos.dominio.Camioneta;
import cl.ucn.ei.pa.sistemavehiculos.dominio.Vehiculo;
public class ListaVehiculos {
private Vehiculo[ ] lv;
private int cantidadVehiculos;
int max;
public ListaVehiculos(int max) {
lv = new Vehiculo [max];
cantidadVehiculos =0;
this.max = max;
}
public int getCantidadVehiculos() {
return cantidadVehiculos;
}
public Vehiculo getVehiculoI (int i) {
if (i >= 0 && i < cantidadVehiculos){
return lv[i];
}
return null;
}
@Override
public String toString() {
String salida = "";
for(int i = 0; i < cantidadVehiculos; i++){
Vehiculo vehiculo = getVehiculoI(i);
package cl.ucn.ei.pa.sistemavehiculos.logica;
import cl.ucn.ei.pa.sistemavehiculos.dominio.*;
}
2.244
package cl.ucn.ei.pa.sistemavehiculos.logica;
import cl.ucn.ei.pa.sistemavehiculos.dominio.*;
public SistemaVehiculosImpl(){
listaVehiculos = new ListaVehiculos(10);
}
return ingreso;
}
2.245
for(int i=0;
i<listaVehiculos.getCantidadVehiculos();i++){
Vehiculo vehiculo =
listaVehiculos.getVehiculoI(i);
Vehiculo vehiculo =
listaVehiculos.getVehiculoI(i);
if (vehiculo instanceof Camioneta){
Camioneta camioneta = (Camioneta) vehiculo;
if (camioneta.getCapacidadCarga()> mayor){
mayor = camioneta.getCapacidadCarga();
camionetaMasCarga = camioneta;
}
}
}
if(camionetaMasCarga != null){
return camionetaMasCarga.toString();
}
else{
return null;
}
}
}
2.248
package cl.ucn.ei.pa.sistemavehiculos.logica;
import cl.ucn.ei.pa.sistemavehiculos.dominio.*;
import ucn.StdIn;
import ucn.StdOut;
else {
if (tipo == 2) {
StdOut.print("Ingrese patente = ");
patente = StdIn.readString();
StdOut.print("Ingrese la marca =");
marca = StdIn.readString();
StdOut.print("Ingrese agno fabricacion= ");
agno = StdIn.readInt();
StdOut.print("Ingrese capacidad carga = ");
int capacidadCarga = StdIn.readInt();
boolean ingreso =
sistema.ingresarCamioneta(patente,
marca, agno, capacidadCarga);
if(!ingreso){
StdOut.println("No se hizo el ingreso
de la camioneta. No hay espacio");
}
}
}
}
case 1:
leerUnVehiculo (sistema);
break;
case 2:
StdOut.println(" ");
StdOut.println(sistema.
obtenerDatosVehiculos());
break;
case 3:
StdOut.print("Patente a buscar: ") ;
String patente = StdIn.readString();
try{
StdOut.println(" ");
StdOut.println(sistema.
obtenerDatosVehiculo(patente));
}catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}
break;
2.251
} //fin switch
desplegarMenu();
StdOut.print("Ingrese opcion:");
opcion = StdIn.readInt();
}
}
m1()
v m2() c
m3()
Auto
Camioneta - int kilometraje
-int capacidadCarga - int capacidadEstanque
+ Camioneta(String patente,
+ Auto(String patente, String marca,
String marca, int agno,
int agno, int kilomeraje,
int capacidadCarga)
int capacidadEstanque)
+ m3() + m4()
v1
¿Desde qué punto de vista quiero ver al objeto: como camioneta o como
vehículo?
Si se ve como vehículo, sólo puedo ver los métodos m1 y m2.
Se puede achicar la interface del objeto (Vehiculo tiene menos cosas que
camioneta)
Vehiculo v1 = c
Vehiculo v1 = (Vehiculo) c;
Si se ve como camioneta, se deben ver los métodos m1, m2 y m3.
No se puede agrandar la interface del objeto (Camioneta tiene más cosas
que Vehiculo)
Camioneta c = v
Si el vehículo v no es camioneta si
Por lo tanto: Camioneta c = (Camioneta) v compila, pero lanza una excepción
2.253
Ejemplo 3
Se tiene información de los funcionarios de la empresa de computación
Mandiosoft Ltda. en la cual se encuentra la información de cada uno de los 3
tipos de funcionarios del área de desarrollo de sistemas. Estos pueden ser
Programadores, Analistas o Ingenieros.
Todos los funcionarios tienen información en común, como lo es rut,
nombre, dirección, sueldo base y el tipo de funcionario. Además si es
programador interesa el lenguaje de programación que domina (sólo uno por
programador), las horas extras y el nivel de programador (4: experto, 3:
avanzado, 2: intermedio, 1: rookie). De los analistas además interesa saber
los años de experiencia y finalmente de los ingenieros interesa el título y la
cantidad de cargas familiares.
La empresa Mandiosoft desarrolla proyectos para otras empresas, en cada
uno de estos proyectos participa siempre 1 analista, 1 programador y 1
ingeniero. De cada proyecto interesa el nombre, el código, la duración en
meses y su costo total.
Los datos se leen de la siguiente manera:
Se tiene un archivo con los datos de todos los proyectos.
Se tiene un archivo con los datos de todos los funcionarios, donde en cada
registro viene la información de un analista o de un ingeniero o de un
programador. Cada registro debe indicar cuál de ellos es.
Se tiene un archivo con la asignación de los trabajadores a los proyectos.
Por cada registrio viene el código del proyecto y el rut del funcionario
2.254
Requerimientos
Una vez ingresada la información, se necesita:
Listado de Proyectos con los costos involucrados (por meses y total)
Listado de funcionarios con sus respectivos sueldos. No es necesario
desplegar los proyectos en los que participa.
Dado un proyecto entregar el listado de gente involucrada.
Dado un funcionario entregar el listado de proyectos en que participa.
Para cada funcionario ingeniero, su nombre y su título.
Los sueldos se calculan de la sigte forma, para el programador además de su
sueldo base, cada hora extra realizada cuesta $5000 además de un bono extra
de $30000 por nivel y otro bono de 20% del valor total mensual del proyecto
por cada proyecto en el que participa. En el caso del analista su sueldo se
calcula con el sueldo base más un bono de $5000 por cada año de
experiencia más el 25% del valor total mensual del proyecto por cada
proyecto en el que participa. Finalmente el ingeniero recibe un sueldo base,
más $8000 por cada carga familiar más un 30% del valor total mensual del
proyecto por cada proyecto en el que participa.
Suponga que cada funcionario trabaja a lo más en 5 proyectos.
2.255
Modelo del dominio
trabaja
Programador Analista
- String lenguaje
- int horasExtras
- int anosExperiencia Ingeniero
- int nivel
- int $ porcentajePorProyecto=25 - String titulo
+ Analista(String rut, String nombre,
- int $ porcentajePorProyecto=20 - int cantidadCargas
+ Programador(String rut, String nombre,
String dirección, int sueldo,
int añosExperiencia) - int $ porcentajePorProyecto=30
String dirección, int sueldo,
String lenguaje, int horasExtras, int nivel) + calcularSueldo(): int + Ingeniero(String rut, String nombre,
+ calcularSueldo(): int + get y set… String dirección, int sueldo,
+ get y set …. int titulo, int cantidadCargas)
1 + calcularSueldo(): int
Proyecto 1 + get y set…
- int codigo
- int meses 1
- String nombre 1
- int monto
- Funcionario ingeniero ListaProyectos
- Funcionario analista - Proyecto[] lp
- Funcionario programador - int cantidadProyectos
+ Proyecto(String codigo,String nombre, * - int max
int monto,int meses)
+ getCodigo(): int + ListaProyectos(int max)
+ getNombre(): String + ingresar(Proyecto proyecto):
+ getMonto(): int boolean
+ getMeses(): int + buscar(int codigo): Proyecto
+ setIngeniero(Funcionario ingeniero) + getCantidadProyectos(): int
+ setAnalista(Funcionario analista)
+setProgramador(Funcionario programador)
+ getProyectoI(int i): Proyecto
+ getIngeniero(): Funcionario
+ getAnalista(): Funcionario
+ getProgramador(): Funcionario
2.257
Contratos
1 1
SistemaProyectosFuncionariosImpl
- ListaProyectos listaProyectos
- ListaFuncionarios listaFuncionarios
<<implements>>
SistemaProyectosFuncionarios
<<interface>>
+ ingresarAnalista(rut, nombre, direccion, sueldoBase, agnosExperiencia): boolean
+ ingresarProgramador(rut, nombre, direccion, sueldoBase, lenguajeProgramacion,
horasExtra, nivelProgramador): boolean
+ ingresarIngeniero(rut,nombre,direccion,sueldoBase,titulo,cantidadCargas):boolean
+ ingresarProyecto(codigo, nombre, monto, meses): boolean
+ asociarFuncionarioProyecto ( codigoProyecto, rut);
+ obtenerDatosProyectos(): String
+ obtenerDatosFuncionarios(): String
+ obtenerDatosFuncionariosProyecto(): String
+ obtenerDatosProyectosFuncionario(rut):String
+ obtenerDatosIngenieros(): String
2.261
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica.ListaProyectos;
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica.ListaProyectos;
public class Programador extends Funcionario {
private String lenguaje;
private int horasExtra;
private int nivel;
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio.Proyecto;
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;
}
2.272
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio.*;
public SistemaFuncionariosProyectosImpl() {
this.listaProyectos = new ListaProyectos(6);
this.listaFuncionarios=new ListaFuncionarios(30);
}
Funcionario funcionario =
listaFuncionarios.getFuncionarioI(i);
}
2.277
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;
import java.io.IOException;
import ucn.ArchivoEntrada;
import ucn.Registro;
import ucn.StdIn;
import ucn.StdOut;
public class App {
leerProyectos(sistema);
leerFuncionarios(sistema);
leerPersonalProyectos(sistema);
StdOut.println(sistema.obtenerDatosProyectos());
StdOut.println(sistema.obtenerDatosFuncionarios());
StdOut.println(sistema.obtenerDatosIngenieros());
}
2.278
ArchivoEntrada archivo =
new ArchivoEntrada("Funcionarios.txt");
boolean ingreso = true;
while(!archivo.isEndFile() && ingreso) {
Registro registro = archivo.getRegistro();
int tipo = registro.getInt();
if (tipo == 1) {//Programador
String rut = registro.getString();
String nombre = registro.getString();
String direccion = registro.getString();
int sueldoBase=registro.getInt();
String lenguaje = registro.getString();
int horasExtra=registro.getInt();
int nivel=registro.getInt();
ingreso = sistema.ingresarProgramador(rut, nombre,
direccion,sueldoBase,lenguaje,horasExtra,nivel);
if(!ingreso) {
StdOut.println("No hay espacio para mas");
}
}
else {
if(tipo == 2) {//Analista
String rut = registro.getString();
String nombre = registro.getString();
String direccion = registro.getString();
int sueldoBase=registro.getInt();
int agnosExperiencia=registro.getInt();
ingreso = sistema.ingresarAnalista(rut, nombre,
direccion,sueldoBase,agnosExperiencia);
if(!ingreso) {
StdOut.println("No hay espacio para mas ");
}
}
2.279
else {//Ingeniero
String rut = registro.getString();
String nombre = registro.getString();
String direccion = registro.getString();
int sueldoBase=registro.getInt();
String titulo = registro.getString();
int cantidadCargas=registro.getInt();
ingreso = sistema.ingresarIngeniero(rut, nombre,
direccion,sueldoBase,titulo,cantidadCargas);
if(!ingreso) {
StdOut.println("No hay espacio para mas");
}
}
}
}
archivo.close();
StdOut.println("Terminado de leer el archivo Funcionarios");
}
}
2.281
Ejercicios Propuestos
A) Ejercicio: Programa para una empresa de capacitación.
“Soy el Director de una empresa de capacitación que imparte cursos en el
área de tecnología de información. Dictamos muchos cursos, cada uno de
los cuales tiene un código, un nombre y una tarifa.
Programación en UNIX y Programación SQL, son dos de nuestros cursos
más populares. Los cursos pueden durar desde un día a cuatro días. Un
instructor puede enseñar varios cursos. Pablo Rogers y María González, son
dos de nuestros principales instructores. Para cada instructor se necesita
conocer, su nombre y su número telefónico. Cada curso es impartido por un
único instructor. Primero se crea un curso, y luego se le asigna el profesor.
Los estudiantes pueden tomar varios cursos a la vez; para cada estudiante se
necesita conocer su nombre y su número telefónico. Algunos de nuestros
estudiantes y profesores en algunas ocasiones no proporcionan sus números
telefónicos.”
Para el enunciado anterior, se pide el diagrama de clases.
Además, la empresa cuenta con un conjunto de vehículos, los que pueden ser
asignados a los empleados (máximo un vehículo por empleado). Para cada
vehículo se registra:
Código
Fecha de su última mantención
Fecha de expiración de la revisión técnica
Lectura del cuenta kilómetros
Capacidad del estanque de combustible
Algunos empleados trabajan con contrato por horas. A ellos se les contrata
por una cierta cantidad de horas mensuales y se acuerda con cada uno el
precio a cancelar por hora. En el momento de pagarles se verifica la
cantidad total de horas trabajadas en el mes y si se registran horas de sobre
tiempo, se les paga 1,5 veces su precio normal por cada hora extra.
Se necesita: