0% encontró este documento útil (0 votos)
143 vistas

Capitulo2POOEnJava PDF

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
143 vistas

Capitulo2POOEnJava PDF

Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 274

2.

1
CAPÍTULO II: PROGRAMACIÓN ORIENTADA AL
OBJETO CON JAVA

2.1. Aproximación a la orientación al objeto

Se trata de resolver problemas, identificando los objetos asociados con el


problema y convirtiéndolos en objetos del programa.

Por ejemplo, son objetos:


José García
Compañía ABC S.A.
Lassie
Proceso Número 7468

Un objeto es, sencillamente, algo que tiene sentido en el contexto de la


aplicación.
Un objeto tiene estado, exhibe una conducta bien definida y tiene una
identidad única.
Ejemplo del objeto martillo
2.2
Conceptos asociados en la orientación al objeto

 Abstracción: Se enfoca en las características esenciales de algún objeto,


relativa a la perspectiva de quien mira al objeto.

 Encapsulación: Oculta los detalles de la implementación de un objeto.


2.3
Para la encapsulación se deben respetar los siguientes puntos:
 La abstracción de un objeto debería preceder a las decisiones sobre su
implementación.
 Una vez que se ha seleccionado la implementación, debe tratarse como
un secreto de la abstracción, oculto para la mayoría de los clientes.
 Ninguna parte de un sistema complejo debe depender de los detalles
internos de otras partes.

El elemento de la abstracción es la clase.

 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.

La modularización consiste en dividir un programa en módulos que se


puedan compilar por separado, pero que tienen conexiones con otros
módulos.

La modularidad es la propiedad de un sistema que permite su


descomposición en un conjunto de módulos cohesivos y débilmente
acoplados.

La modularidad empaqueta las abstracciones en unidades discretas.

En el caso de Java se hace a través de los paquetes.


2.4

 Jerarquía Conceptos que se verán más adelante


 Polimorfismo
Una ventaja de utilizar la orientación al objeto es que la brecha semántica se
minimiza, ya que los objetos de la realidad son directamente mapeados en
objetos en el modelo.
Diferencia semántica entre la realidad y el modelo
Realidad
Casa Auto
Tom Árbol

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.

Cuando se especifica la solución, aparecen nuevos objetos, desde el punto de


vista de la solución del problema.

Capas de especificaciones de objetos resultantes del


proceso de refinamiento

¿Qué? Dominio del problema


Objetos definidos durante
el análisis

Especificación de la
solución
Objetos definidos durante el
diseño

¿Cómo?
2.6
2.2. Modelo del dominio

 “Un modelo de dominio es una representación de conceptos en un


dominio del problema” [MO95, Fowler96]

 “El modelo de dominio representa las “cosas” que existen o eventos que
transcurren en el entorno de un negocio.” [I. Jacobsen]

Ejemplos de modelo del dominio

Ejemplo 1 La flecha representa en qué


dirección se lee el verbo
tiene
Persona Compañia
nombre 1..* 1 nombre
apellido
salario
1
propietario <<Regla>>
Si una persona no es empleado
de una compañía, ésta no
* puede ser propietario de una
Camioneta camioneta
patente
marca
año
2.7

Relacionamientos entre conceptos

Concepto de relacionamiento

El relacionamiento entre conceptos es una asociación natural en el contexto


del problema

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 y sólo 1” “Cero o más”

1 Coloca *
Cliente Orden

 La línea entre las clases muestra el relacionamiento.

 El verbo describe el relacionamiento.

 Notar que todos los relacionamientos son bidireccionales, en forma


implícita, indicando con ello que pueden ser interpretados en ambas
direcciones.
2.8
Multiplicidad del relacionamiento
La multiplicidad define el mínimo y el máximo número de ocurrencias de un
concepto asociados a una única ocurrencia del concepto relacionado.

Debido a que todos los relacionamientos son bidireccionales, la


multiplicidad debe ser definida en ambas direcciones, para cada
relacionamiento.

Tipos de multiplicidad
1
Concepto 1 y sólo 1

* Concepto 0 ó más

n..m
Concepto
Entre n y m
2.9
La multiplicidad define cuántas instancias de un concepto A pueden
asociarse a un concepto B.

Ejemplos
1..* pertenece 1
Profesor Depto

1..2 dicta 0..4


Profesor Asignatura

1..* pertenece 1
Alumno Carrera

0..1 se le ha prestado 1..3


Alumno Libro
2.10
Características del modelo del dominio

 Concepto: Denota un tipo de objeto.

 Atributos: Describen un conjunto de valores asociados a un concepto.

 Asociaciones: Representa cómo dos o más conceptos se encuentran


vinculados.

 Reglas adicionales: Se describen mediante notas las reglas que no


pueden ser representadas por la simbología.

Concepto. Los tipos de conceptos pueden ser:


 Objetos de negocio: Representa cosas que son manipuladas en un
negocio. (Ej: Boleta)
 Objetos del mundo real: Cosas que la empresa realiza un seguimiento.
(Personas, Sitios)
 Eventos que transcurren: Venta y pagos.

Recomendaciones para el Modelo del Dominio


 Listar los conceptos idóneos
 Dibujar los conceptos en un modelo de dominio
 Incorporar las asociaciones necesarias
 Agregar atributos necesarios

 ¿Cómo identificar Conceptos?


 Sustantivos y frases en descripción textual del dominio
 ¿Cómo identificar Atributos?
 Concepto que puede ser representado por un número o un texto.
2.11

Caso de Estudio: Modelo del dominio


 Desarrollar un modelo de dominio que permita modelar el
requerimiento de la Farmacia “Dr Pepito”.
 La Farmacia “Dr Pepito” requiere de un software que le permita
administrar venta de remedios.
 El software debe considerar los siguientes aspectos:
 Algunos medicamentos sólo pueden ser vendidos bajo receta
medica, o en su defecto, con la aprobación del farmacéutico.
 Los vendedores deberán registrar los remedios que se compren en
un TPV, en donde se ingresará el código del remedio, cantidad y
% de descuento.
 Al finalizar la venta, los clientes podrán cancelar los remedios en
efectivo, tarjeta o cheque al día.
 Al terminar el pago, el vendedor le entrega los productos al
cliente junto con el comprobante de pago.
2.12
Conceptos

Comprobante de pago
2.13
Asociaciones

1..* 1..* 0..*

1..* Comprobante de pago

1..*

1..*

1..* 1..*
2.14
Atributos

nombre rut
dirección

rut

1..* 1..* 0..*

contiene Comprobante de pago


1..*
identificador
código 1..* fecha
total

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

 El objetivo es que lo entienda el cliente

 A diferencia, el Diagrama de Clases es para el diseñador del software

 No se necesita colocar el tipo de los atributos. El cliente no sabe de


eso

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 .

Construya el modelo del dominio

* trabajan 1..*
Proyecto Empleado
Código proyecto Rut empleado
Nombre proyecto Nombre empleado
Dedicacion
horas a la semana

Otra forma

Proyecto tiene tiene Empleado


Código 1 1 rut
Nombre Nombre

1..* *
Dedicacion
horas
2.22
Ejercicio
Se debe construir una aplicación para que el jefe de carrra 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 alumnos 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

Otra forma
Estudiante
1 Asignatura
tiene tiene
Rut 1
Código
Nombre Nombre
Créditos
1..* 1..*
Inscripcion
Jefe de Carrera Oportunidad
2.23
2.3. Conceptos de orientación al objeto
2.3.1. Cinco palabras claves del vocabulario O.O

Objeto: Colección de datos privados y operaciones públicas.

Clase: Descripción de un conjunto de objetos con propiedades


(atributos) similares, con relaciones comunes con otros
y con una semántica común.

Instancia: Una instancia de una clase, es un objeto de esa clase.

Método: Un cuerpo de procedimiento que implementa una


operación.

Mensaje: Un llamado a un procedimiento. Un requerimiento


para ejecutar un método.

Ejemplo:
 Clase con sus atributos:

Persona
nombre: String
edad : int
2.24
 Objetos con sus valores
p1: Persona p2: Persona

nombre = Juan García nombre = María Perez


edad = 24 edad = 40

Objeto:

 Colección de campos, junto a una colección de procedimientos


(llamados métodos) que operan en los campos.

 Un objeto encapsula los componentes pasivos (campos) y los


componentes activos (métodos) en una única entidad.

 Este encapsulamiento incrementa la modularidad del programa: al aislar


un objeto del resto del programa, se obtiene un programa que es más
fácil de entender y de modificar.

 El estado de un objeto, es representado por un conjunto de atributos.

 Los atributos mantienen información acerca de un objeto.

 El comportamiento de un objeto, representa las acciones que pueden


ser realizadas sobre el objeto.

 Estas acciones ocurren cuando un mensaje es enviado hacia el objeto.


2.25
Clase:
 Todos los tipos que no son primitivos son CLASES

 Una clase es un conjunto de objetos que comparten una estructura


común y un comportamiento común.

 Un objeto particular es simplemente una instancia de una clase.

 Un objeto no es una clase.

 ¡ Una clase puede ser un objeto ! (Por lo tanto, a la clase se le puede


enviar un mensaje, por ejemplo, new)

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

getNumeroMatricula(): String getNombre(): String

a1: Alumno a2: Alumno p1: Profesor p2: Profesor


numeroMatricula = 111 numeroMatricula = 222 nombre = Raúl Vega nombre = Pedro Soto
nombre = Juan García nombre = Juan Perez tipo = 1 tipo = 2
edad = 24 edad = 19
2.28
2.3.2. Interface, implementación y diagrama de una clase

Interface de una clase


 La interface de una clase proporciona su vista externa y por lo tanto
enfatiza la abstracción, mientras esconde su estructura y los secretos de su
comportamiento.

 En un nivel abstracto, una clase es una interface que define la conducta de


sus objetos

Las operaciones, o funciones e interfaces,


proporcionan un canal de comunicación hacia
y desde el objeto de la clase.

requerimiento de la operación Caja negra del


Programa de objeto de la
resultado de la operación
Aplicación clase

Implementación de una clase


 La implementación de una clase corresponde a su vista interna, la que
abarca los secretos de su comportamiento.
 La implementación de una clase consiste principalmente de la
implementación de todas las operaciones definidas en la interface de la
clase.
 Se puede dividir la interface de una clase en tres tipos de visibilidades:
 PUBLIC
 PROTECTED
 PRIVATE
2.29
 PUBLIC: Es una declaración que está visible a todos los clientes.

 PROTECTED: Es una declaración que está visible solamente a la


misma clase y a sus subclases.

 PRIVATE: Es una declaración que está visible solamente a la misma


clase.

Diagrama de clase

Nombre de Clase
Visibilidad tipo de dato 1 nombre atributo 1
Visibilidad tipo de dato 2 nombre atributo 2
...

Visibilidad nombre operación 1 (lista argum.1): tipo de resultado 1

Visibilidad nombre operación 2 (lista argum.2): tipo de resultado 2


...

Ejemplo:
Persona
- private - String nombre
+ public - int edad
+ Persona()
+ getEdad(): int
+ getNombre(): String
+ setEdad()
+ setNombre()
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.

 Existe tanto como lo hace la instancia, es decir, la existencia de la


variable de instancia depende de la existencia del objeto que la contiene.

Variable de Clase:
 Variable compartida por todas las instancias de una clase (una ÚNICA
copia).
 Todos los objetos de la clase la pueden ver.

Ejemplo:

CuentaAhorro
Variable de
- int numero instancia
- int saldo
- $ double interes

Variable de clase
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

En la práctica se ha encontrado que un cliente realiza típicamente cinco tipos


de operaciones sobre un objeto:

 Modificador
 Selector
 Iterador
 Constructor
 Destructor

Modificador: Es una operación que altera el estado de un objeto


(Métodos set).

Selector: Es una operación que accesa al estado de un objeto,


pero no lo altera (Métodos get).

Iterador: Es una operación que permite que todas las partes de un


objeto sean accesadas, en algún orden bien definido.

Constructor: Es una operación que crea un objeto y/o inicializa


su estado.

Destructor: Es una operación que libera el estado de un objeto


y/o destruye el objeto mismo.
2.33
2.3.5. Declaración, creación, asignación, comparación y
destrucción de objetos

A. Declaración del objeto

NombreClase nombreVariable;

La declaración no establece almacenamiento para la variable.


Ejemplo: Persona p;

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:

new NombreClase (parámetros_actuales);


Ejemplo: new Persona (25);

La evaluación de esta expresión significa:


a) Asignación de memoria para un nuevo objeto de la clase
NombreClase, asociándole valores iniciales a las variables del objeto.
b) Se invoca el constructor apropiado de la clase, con los parámetros
correspondientes.
c) Se regresa como resultado la referencia al objeto creado.

Si no hay rutina constructora, se crea igual el espacio y todos los atributos


quedan en nulo.
2.34
C. Asignación de Objetos

Ejemplo: miObjeto = tuObjeto;

“Shallow Copy” o Copia Superficial

Nuevo almacenamiento no es creado para el objeto destino, en la


asignación de objetos.
x=y

x y

D. Comparación de Objetos

Los operadores == (igual) y != (no igual) se utilizan para comparar


expresiones cuyos valores son referencias a objetos.

Esta comparación prueba si al evaluar las dos expresiones, el resultado es


o no, la referencia al mismo objeto (identidad versus igualdad).

Semántica por referencia


Las variables de tipo objeto almacenan referencias al objeto. Los objetos
en JAVA, tienen una “Semántica por Referencia” (“Reference
Semantics”). Es decir, ellos son realmente punteros.

Ejemplo: x, y son objetos de una clase


a b
x = y; x e y referencian
x y if (x = = y) verdadero al mismo objeto
2.35
Ejemplo de identidad:

String x, y if (x = = y)  falso
(1)
a a if (x.equals(y))  verdadero

(2) x = y;
(2)
x y if ( x == y)  true

Ejemplo de igualdad:

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.

La recuperación de memoria de los objetos, que ya no son útiles, se realiza


automáticamente por el proceso recolector de basura, el cual se ejecuta de
manera concurrente con el programa en Java.
2.36
Ejemplo:

En el diagrama de
Alumno clases, los métodos
- String nombre deben ir con sus
- String numeroMatricula parámetros
+ Alumno()
+ getNombre(): String
+ getNumeroMatricula(): String
+ setNombre()
+ setNumeroMatricula()
+ toString(): String

No todo atributo debe tener el


Toda clase método set, por ejemplo, para el
tiene un número de matrícula.
método En general, si en la aplicación no
toString() existe la posibilidad de cambiar el
valor de un atributo, no es
necesario el set.

Colocaremos todos los set


2.37

public class Alumno {


private String nombre;
private String numeroMatricula;

/**
* @param nom
* @param matricula
*/
public Alumno(String nom, String matricula) {
nombre = nom;
numeroMatricula=matricula;
}

/**
* @return the nombre
*/
public String getNombre() {
return nombre;
}

/**
* @param nom the nombre to set
*/
public void setNombre(String nom) {
nombre = nom;
}

/**
* @return the numeroMatricula
*/
public String getNumeroMatricula() {
return numeroMatricula;
}

/**
* @param matricula the
*numeroMatricula to set
*/
public void setNumeroMatricula(String matricula) {
numeroMatricula=matricula;
} El método toString() sobre
/* (non-Javadoc) escribe desde
* @see java.lang.Object#toString() java.lang.Objetct.toString
*/
@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.

Diagrama de clases
CuentaBancaria Nombre de la Clase
- int saldo Variable de Instancia
+ CuentaBancaria()
+ depositar()
+ girar(): boolean
+ getSaldo(): int Métodos de Instancia
+ setSaldo() La clase CuentaBancaria podría
+ toString(): String también tener un número

public class CuentaBancaria {

private int saldo;

/**
* @param saldo
*/
public CuentaBancaria(int saldoInicial) {
saldo = saldoInicial;
}

/**
* @return the saldo
*/
public int getSaldo() {
return saldo;
}
2.39

/**
* @param saldo the saldo to set
*/
public void setSaldo(int saldoNuevo) {
saldo = saldoNuevo;
}

/* (non-Javadoc) Toda clase tiene


* @see java.lang.Object#toString() un método
*/
@Override
toString()
public String toString() {
return "CuentaBancaria [saldo=" + saldo + "]";
}

public void depositar(int cantidad){


saldo = saldo + cantidad;
}

public boolean girar(int cantidad){


if (saldo >= cantidad){
saldo = saldo - cantidad;
return true;
}
else {
return false;
}
}

}//Fin cuentaBancaria
2.40

import ucn.StdOut;

public class BankApp {

public static void main(String[] args) {


//Crea una cuenta
CuentaBancaria cuentaBancaria = new CuentaBancaria(100);

StdOut.println("Saldo antes de las transacciones: "


+cuentaBancaria.getSaldo());
StdOut.println("Cuenta bancaria antes de las transacciones: "
+ cuentaBancaria.toString());

cuentaBancaria.depositar(74); // efectuar un depósito


cuentaBancaria.girar(20); // efectuar un retiro

StdOut.println("Despues de las transacciones: " +


cuentaBancaria.getSaldo());
StdOut.println("Cuenta bancaria antes de las transacciones: "
+ cuentaBancaria.toString());
}//fin main
La cantidad a depositar o que se gira debe ser mayor
que cero. Esa validación debe hacerse en la App
}//Fin BankApp

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]

Diagrama de objetos
cuentaBancaria: CuentaBancaria
saldo = 100
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 debe tener
setCreditos() el método set, por ejemplo,
para el código no es
necesario

Solución

Asignatura
- String codigo
- int creditos
+ Asignatura()
+ getCodigo(): String
+ getCreditos(): int
+ setCodigo()
+ setCreditos()
2.42
public class Asignatura {
private String codigo;
private int creditos;

public Asignatura(String cod, int cred) {


codigo = cod;
creditos = cred;
}
public String getCodigo() {
return codigo;
}
public int getCreditos() {
return creditos;
}
public void setCodigo(String cod) {
codigo = cod;
}
public void setCreditos(int cred) {
creditos = cred;
}

} Podríamos tener el método toString()

public class App {


public static void main (String [ ] args) {
Asignatura asignatura = new Asignatura (“cc 571”, 14);
StdOut.println(“Datos de la asignatura: Codigo = ” +
asignatura.getCodigo() + “ creditos= ” +
asignatura.getCreditos());
}
}
2.43
Notas:
 La rutina constructora no tiene un tipo asociado al resultado, debido a
que retorna el objeto.
 Los parámetros en JAVA son sólo de modo IN.

Ejemplo
El programa siguiente, crea dos objetos Punto diferentes y pone valores
únicos en cada uno.
Cuando no hay rutina constructora,
public class Punto { se crea el objeto quedando todos sus
private int x; atributos nulos
private int y;
Punto p =new Punto()
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()
} + setY()
public int getY(){ + getX(): int
return y; + getY(): int
}
} Podríamos tener el método toString()

public class DosPuntos {

public static void main(String args[]) {


Punto p1 = new Punto();
Punto p2 = new Punto();
2.44
p1.setX(10);
p1.setY(20);

p2.setX(42);
p2.setY(99);

StdOut.println ("x = " + p1.getX() + " y = " + p1.getY());

StdOut.println ("x = " + p2.getX() + " y = " + p2.getY());


}
}
Imprime
p1: Punto p2: Punto x = 10 y = 20
x = null 10 x = null 42 x = 42 y = 99
y = null 20 y = null 99

public class Punto {


private int x;
private int y;

public void init (int xx, int yy) {


x = xx;
y = yy;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
2.45
El programa siguiente, aprovecha el método init para efectuar la
inicialización del objeto.

public class TwoPointsInit {

public static void main(String args[]) {

Punto p1 = new Punto();


Punto p2 = new Punto();

p1.init(10, 20);
p2.init(42, 99);

StdOut.println ("x = " + p1.getX() + " y = " + p1.getY());


StdOut.println ("x = " + p2.getX() + " y = " + p2.getY());
}

}
2.46
2.3.6. Mensajes a THIS

 Dentro de la implementación de un método, el identificador this


representa un parámetro implícito, que referencia al objeto para el cual
el método fue invocado.

 “Un mensaje a this, es un mensaje al mismo objeto”

 En: C++: this


Smalltalk: self
Delphi Pascal: self

 Si el objeto al que se quiere enviar el mensaje es el mismo, se debe usar


el this.

Ejemplo 1 :
Inicializar las variables de una clase, utilizando el constructor.
Punto
- int x
- int y

+ Punto()
+ getX(): int
+ getY(): int
2.47
public class Punto {
private int x;
private int y;

public Punto(int x, int y) {


this.x = x;
this.y = y;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
//…Métodos set
}

public class CrearPunto {

public static void main(String args[]){


Punto punto = new Punto(10, 20);
StdOut.println("x = " + punto.getX() + " y = " + punto.getY());
}
}

Ejemplo 2:
Empleado

+ calcSueldoTotal(): int SueldoFinal =


+ calcDescuentoTotal(): int this.calcSueldoTotal() –
+ calcSueldoFinal(): int this.calcDescuentoTotal();
2.48
2.3.7. Sobrecarga de métodos

Ejemplo 1: Un constructor llama a otro constructor, para construir la


instancia.
public class Punto {
private int x;
private int y;
public Punto(int x, int y) {
this.x = x;
this.y = y;
}
public Punto() {
this(-1, -1); //this.Punto(-1,-1);
}
}

Ejemplo 2: 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;
}
2.49
public int getY(){
return y;
}
}

public class PointCreateAlt {

public static void main(String args[]) {


Punto p = new Punto();
StdOut.println("x = " + p.getX() + " y = " + p.getY());
}
}

Ejemplo 3: Existen dos versiones de un método llamado distancia, asociado a


la clase Punto. Unbmétodo toma un par x, y, y el otro toma otro objeto Punto.
Punto
public class Punto {
private int x; - int x
private int y; - int y

+ Punto()
public Punto(int x, int y) { + setX()
this.x = x; + setY()
this.y = y; + getX(): int
} + getY(): int
+ distancia(int x, int y): double
public int getX(){ + distancia(Punto p): double
return x;
} En el diagrama de clases, se deben colocar
public int getY(){ todas las versiones de los métodos
return y; sobrecargados. Se diferencian por los
} parámetros
//….Métodos set
2.50
public double distancia(int x, int y) {
int dx = this.x - x;
int dy = this.y - y;
return Math.sqrt(dx*dx + dy*dy);
}
public double distancia(Punto p) {
return this.distancia(p.x, p.y);
}
}

public class PointDist {

public static void main (String args[]) {


Punto p1 = new Punto(0, 0);
Punto p2 = new Punto(30, 40);
StdOut.println( "p1 = " + p1.getX() + ", " + p1.getY());
StdOut.println( "p2 = " + p2.getX() + ", " + p2.getY());

StdOut.println( "p1.distancia(p2) = " +


p1.distancia(p2));
StdOut.println( "p1.distancia(60, 80) = " +
p1.distancia(60, 80));
}

} p1: Punto p2: Punto


x=0 x = 30
y=0 y = 40

En el ejemplo se utiliza el método estático sqrt de la clase Math para calcular


la raíz cuadrada de su parámetro.
2.51
2.4. Relacionamientos entre Clases/Objetos

2.4.1. Concepto de relacionamiento

Conceptualmente, los objetos y las clases no existen aisladas.

El relacionamiento entre clases/objetos es una asociación natural en el


problema que existe entre uno o más objetos/clases.

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 y sólo 1” “Cero o más”

1 *
Cliente Orden

 La línea entre las clases muestra el relacionamiento.

2.4.2. Multiplicidad del relacionamiento

Igual que en el modelo del dominio


2.52
Tipos de multiplicidad
1 Clase 1 y sólo 1

* Clase 0 ó más

n..m
Clase Entre n y m

2.4.3. Agregación

Una clase especial de relacionamiento puede existir entre objetos / clases:

 Algunas veces los objetos / clases están formados por otros objetos.

 Un objeto está compuesto por otros objetos.

 Este tipo especial de relacionamiento se llama agregación.

 Un objeto es fabricado con otros objetos.

Ejemplos:

Auto:
 Transmisión
 Tubo de escape
 Motor
 Suspensión
 Ruedas
2.53
Ventana:
 Botones
 Labels
 Menús

Se utiliza el símbolo en un extremo del relacionamiento para indicar


la agregación.

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

2.4.4. Composición
A * B

Compuesto Componente

La diferencia entre composición y agregación es que en la composición si se


elimina el compuesto se elimina también los componentes. En el caso de la
agregación no.
2.55
2.5. Contenedores implementados con arreglos
2.5.1. Clase Contenedor

 Se mejora la interface con los clientes de la clase.

 El usuario de la clase, en este caso Contenedor, debe estar libre para


concentrarse en ¿qué?, en vez de ¿cómo?

¿Qué va a ser insertado?


¿Qué va a ser eliminado?
¿Qué va a ser accesado?, en vez de conocer ¿Cómo estas
actividades son llevadas a cabo?

 El contenedor debe tener métodos tales como: buscar, eliminar, agregar,


obtener el elemento i-ésimo del contenedor, etc.

ListaDoubles

- double [ ] lista
- int cantidadElementos
- int max
+ ListaDoubles()
+ encontrar(): int
+ insertar(): boolean
+ eliminar(): boolean
+ getCantidadElementos(): int
+ getElemI(): double
2.56
// ListaDoubles.java

public class ListaDoubles {

private double[] lista; // referencia el arreglo


private int cantidadElementos;// número de items
private int max; //Máxima cantidad de elementos para el contenedor
//----------------------------------
public ListaDoubles(int max) {// constructor
lista = new double[max];//crea el arreglo
cantidadElementos = 0; // no tiene items todavía
this.max = max;
}
//-----------------------------------
public int encontrar(double claveBusqueda){
// Si encuentra el valor especificado, retorna la posición donde
// lo encuentra. Sino, retorna un -1
int j;
for(j=0; j< cantidadElementos; j++) { // para cada elemento
if(lista[j] == claveBusqueda){ // ¿item encontrado?
break; // sale del loop
}
}
if(j == cantidadElementos) { //no lo encontró
return -1;
}
else{
return j; // si lo encontró, en la posición j
}
} // end econtrar()
2.57
public boolean insertar(double valor){ //inserta elemento en el contenedor
if (cantidadElementos < max) { //Hay espacio
lista[cantidadElementos] = valor; // lo inserta
cantidadElementos ++; // incrementa el tamaño
return true;
}
int j = 0;
else { while( j< cantidadElementos && valor!=lista[j]){
return false; j++;
}
}
}
//-----------------------------------
public boolean eliminar(double valor){
int j;
Busca for(j=0; j< cantidadElementos; j++){
el if( valor == lista[j] ) {
valor break;
}
}
if(j== cantidadElementos){//no lo encontró int pos=this.encontrar(valor);
if (pos != -1){
return false; //Corrimiento
} //…..
}
else { // si lo encontró
//Corrimiento
for(int k=j; k<cantidadElementos - 1;k++){
lista[k] = lista[k+1];
}
cantidadElementos--; // decrementa tamaño
return true;
} //fin else
} // end eliminar()
//-----------------------------------
public int getCantidadElementos() {
return cantidadElementos;
}
//-----------------------------------
public double getElemI(int i) { Se debe chequear que el i esté en
return lista[i]; rango del 0 y cantidadElementos
}
}// end class ListaDoubles
2.58
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()
} // end class ListaDoublesApp
2.59
Ejercicio
En el ejemplo anterior, el contenedor almacena datos de un tipo primitivo. El
siguiente ejemplo, muestra cómo guardar objetos.
* ListaPersonas
Persona
- String apellido - Persona [ ] lista
- String nombre - int cantidadPersonas
- int edad - int max
+ Persona()
+ getApellido():String
+ getNombre(): String + ListaPersonas()
+ getEdad(): int + encontrarPersona(): Persona
+ setApellido() + insertar(): boolean
+ setNombre() + eliminar(): boolean
+ setEdad() + getCantidadPersonas(): int
+ toString():String + getPersonaI(): Persona
+ toString(): String

 Toda clase tiene un método toString()


 El método toString() sobre escribe desde
java.lang.Objetct.toString

public class Persona {


private String apellido;
private String nombre;
private int edad;
/**
* @param apellido
* @param nombre
* @param edad
*/
public Persona(String apellido, String nombre, int edad) {
this.apellido = apellido;
this.nombre = nombre;
this.edad = edad;
}
2.60
/**
* @return the apellido
*/
public String getApellido() {
return apellido;
}
/**
* @param apellido the apellido to set
*/
public void setApellido(String apellido) {
this.apellido = apellido;
}
/**
* @return the nombre
*/
public String getNombre() {
return nombre;
}
/**
* @param nombre the nombre to set
*/
public void setNombre(String nombre) {
this.nombre = nombre;
}
/**
* @return the edad
*/
public int getEdad() {
return edad;
}
/**
* @param edad the edad to set
*/
public void setEdad(int edad) {
this.edad = edad;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Persona [apellido=" + apellido + ", nombre=" +
nombre + ", edad=" + edad + "]";
}
}//Fin Persona
2.61
public class ListaPersonas {

private Persona []lista;


private int cantidadPersonas;
private int max;

public ListaPersonas(int max){


lista = new Persona [max];
cantidadPersonas = 0;
this.max = max;
}

En el método ingresarPersona, es mejor traspasar el


objeto que recibir sus atributos y crearlo. Lo
anterior, debido a que si hay un cambio en la
persona habría que intervenir este código.

public boolean ingresarPersona(Persona persona){


if (cantidadPersonas < max){
lista[cantidadPersonas]= persona;
cantidadPersonas ++;
return true;
}
else{
return false;
}
}

public int getCantidadPersonas(){


return cantidadPersonas;
}

public Persona getPersonaI(int i){


if (i >=0 && i < cantidadPersonas){
return lista[i];
}
else{
return null;
}
}
2.62
public Persona buscarPersona(String apellido){
int i;
for(i = 0; i < cantidadPersonas; i++){
if (lista[i].getApellido().equals(apellido)){
break;
}
}
if (i == cantidadPersonas){
return null;
}
else{
return lista[i];
}
}
public boolean eliminar(String apellido) {
// elimina la persona del contenedor
int j;
for(j=0; j< cantidadPersonas; j++){
if(lista[j].getApellido().equals(apellido)) {
break; //sale del for
}
}
if(j== cantidadPersonas) { // no lo encontró
return false;
}
else { // lo encontró
for(int k=j;k<cantidadPersonas-1;k++){//corrimiento
lista[k] = lista[k+1];
}
cantidadPersonas --; // decrementa el tamaño
return true;
} //end else Es mejor sobreescribir el
} //Fin eliminar método toString que se
obtiene desde el Eclipse
//Se obtiene un string con todos los
//elementos de la lista
o NetBeans para un
public String toString(){ contendor.
String r = ""; Lo anterior debido a que
for (int i=0;i<cantidadPersonas;i++){ invoca toString para
r=r+lista[i].toString()+ "\n"; cada elemento y puede
} que el contedor no esté
return r; lleno y existan espacios
} nulos
}//Fin ListaPersonas
2.63

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();
}

public static void main(String[] args) {


int maxSize = 100; // tamaño del contenedor
ListaPersonas listaPersonas =
new ListaPersonas(maxSize);
//referencia y crea la lista

// 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);
listaPersonas.ingresarPersona(p3);
Persona p4 = new Persona("Salazar","Rozana", 29);
listaPersonas.ingresarPersona(p4);
Persona p5 = new Persona("Galleguillos","Ingrid",72);
listaPersonas.ingresarPersona(p5);
Persona p6 = new Persona("Alfaro","Eduardo",54);
listaPersonas.ingresarPersona(p6);
Persona p7 = new Persona("Sanchez", "Yazmin", 22);
listaPersonas.ingresarPersona(p7);
Persona p8 = new Persona("Vergara","Vladimir",18);
listaPersonas.ingresarPersona(p8);
2.64

desplegarPersonas(listaPersonas);
StdOut.println("Despliegue de las personas");
StdOut.println(listaPersonas.toString());
StdOut.println();
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();
StdOut.println("Eliminando Viorklumds, Vega y Alfaro");
// elimina 3 items
boolean pudoEliminar=listaPersonas.eliminar("Viorklumds");
if (pudoEliminar){
StdOut.println("si elimino a Viorklumds");
}
pudoEliminar =listaPersonas.eliminar("Vega");
if (pudoEliminar){
StdOut.println("si elimino a Vega");
}
pudoEliminar =listaPersonas.eliminar("Alfaro");
if (pudoEliminar){
StdOut.println("si elimino a Alfaro");
}
StdOut.println();
desplegarPersonas(listaPersonas);
StdOut.println("Despliegue de las personas");
StdOut.println(listaPersonas.toString());
StdOut.println();

}//Fin main
}// Fin ListaPersonasApp
2.65
Se imprime:
Despliegue de las personas
Martinez Jose 24
Tapia Luis 37
Viorklumds Jorge 43
Ferrada Cecilia 63 Despliegue con método estático de la
Vega Carlos 21 App desplegarPersonas
Salazar Rozana 29
Galleguillos Ingrid 72
Alfaro Eduardo 54
Sanchez Yazmin 22
Vergara Vladimir 18

Despliegue de las personas


Persona [apellido=Martinez, nombre=Jose, edad=24] Despliegue
Persona [apellido=Tapia, nombre=Luis, edad=37]
Persona [apellido=Viorklumds, nombre=Jorge, edad=43] utilizando en
Persona [apellido=Ferrada, nombre=Cecilia, edad=63] StdOut.println
Persona [apellido=Vega, nombre=Carlos, edad=21] el método
Persona [apellido=Salazar, nombre=Rozana, edad=29]
Persona [apellido=Galleguillos, nombre=Ingrid, edad=72]
toString de la
Persona [apellido=Alfaro, nombre=Eduardo, edad=54] clase
Persona [apellido=Sanchez, nombre=Yazmin, edad=22] ListaPersonas
Persona [apellido=Vergara, nombre=Vladimir, edad=18]

Buscando a Martinez
Encontrado Martinez Jose 24

Eliminando Viorklumds, Vega y Alfaro


si elimino a Viorklumds
si elimino a Vega
si elimino a Alfaro

Despliegue de las personas


Martinez Jose 24
Tapia Luis 37
Ferrada Cecilia 63
Salazar Rozana 29
Galleguillos Ingrid 72
Sanchez Yazmin 22
Vergara Vladimir 18

Despliegue de las personas


Persona [apellido=Martinez, nombre=Jose, edad=24]
Persona [apellido=Tapia, nombre=Luis, edad=37]
Persona [apellido=Ferrada, nombre=Cecilia, edad=63]
Persona [apellido=Salazar, nombre=Rozana, edad=29]
Persona [apellido=Galleguillos, nombre=Ingrid, edad=72]
Persona [apellido=Sanchez, nombre=Yazmin, edad=22]
Persona [apellido=Vergara, nombre=Vladimir, edad=18]
2.66
Supongamos que en la creación de los objetos Persona se usará la misma
referencia p.
// inserta 10 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);
p = new Persona("Vega","Carlos",21);
listaPersonas.ingresarPersona(p);
p = new Persona("Salazar","Rozana", 29);
listaPersonas.ingresarPersona(p);
p = new Persona("Galleguillos","Ingrid",72);
listaPersonas.ingresarPersona(p);
p = new Persona("Alfaro","Eduardo",54);
listaPersonas.ingresarPersona(p);
p = new Persona("Sanchez", "Yazmin", 22);
listaPersonas.ingresarPersona(p);
p = new Persona("Vergara","Vladimir",18);
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
2.67

p = listaPersonas[0]

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]

El objeto Persona no es basura, ya que se puede llegar a él a través de listaPersonas[0]


apellido: Martinez
nombre: Jose
edad: 24
2.68
2.5.2. Ordenamiento de un contenedor de objetos

Persona * ListaPersonas
- String apellido - Persona [] lp
- String nombre - int cantidadPersonas
- int edad
+ ListaPersonas()
+ Persona() + insertar(): boolean
+ get y set …. + insertionSort()
+ toString(): String + getCantidadPersonas(): int
+ getPersonaI(i): Persona
+ toString(): String

public class Persona {


private String apellido;
private String nombre;
private int edad;

public Persona(String apellido, String nombre, int edad) {//constructor


this.apellido = apellido;
this.nombre = nombre;
this.edad = edad
}

public String getApellido(){ // obtiene el apellido


return apellido;
}

// get y set ….

// toString()….

}//fin clase Persona


2.69
public class ListaPersonas {
private Persona[] lista; //referencia al arreglo
private int cantidadPersonas; //número de ítems
private int max;

public ListaPersonas(int max) { //constructor


lista = new Persona[max]; //crea el arreglo
cantidadPersonas = 0; //no hay items todavía
this.max = max;
}

public boolean insertar(Persona persona){


if (cantidadPersonas < max){
lista[cantidadPersonas] = persona;
cantidadPersonas++; //incrementa el tamaño
return true;
}
else{
return false;
}
}

public int getCantidadPersonas(){


return cantidadPersonas;
}

public Persona getPersonaI(int i){


if (i >= 0 && i < cantidadPersonas){
return lista[i];
}
return null;
}
2.70
public void insertionSort(){
int in, out;
for(out=l; out<cantidadPersonas; out++) {
Persona temp = lista[out];
in = out;
while(in>0 &&
lista[in-1].getApellido().compareTo(temp.getApellido ())>0){
lista[in] = lista[in-1];
--in;
}
lista[in] = temp;
} //fin del for;

} //fin insertionSort()

//toString()....

} //fin clase ListaPersonas

public class ListaPersonasApp {


public static void main(String[] args){
int max = 100; //tamaño del contenedor
ListaPersonas listaPersonas; //referencia al contenedor
//Crea el contenedor
listaPersonas = new ListaPersonas(max) ;
listaPersonas.insertar(new Persona("Martínez", "José", 24));
listaPersonas.insertar(new Persona("Tapia","Luis",37));
listaPersonas.insertar(new Persona("Viorklumds", "Jorge", 43));
listaPersonas.insertar(new Persona("Ferrada", "Cecilia", 63));
listaPersonas.insertar(new Persona("Salazar","Rozana", 29));
2.71
Persona persona = new Persona("Galleguillos","Ingrid",72);
listaPersonas.insertar(persona);
Persona persona1 = new Persona("Alfaro","Eduardo",54);
listaPersonas.insertar(persona1);
Persona persona2 = new Persona("Sanchez", "Yazmin", 22);
listaPersonas.insertar(persona2);
Persona persona3 = new Persona("Vergara","Vladimir",18);
listaPersonas.insertar(persona3);

StdOut.println(“Antes de ordenar:”) ;
desplegarPersonas(listaPersonas); Se podría desplegar la
lista de personas usando
listaPersonas.insertionSort(); el método toString(),
como en el caso del
StdOut.println(“Despues de ordenar:”) ; ejemplo anterior
desplegarPersonas(listaPersonas);

}//fin main()

public static void desplegarPersonas (ListaPersonas listaPersonas){


//Despliega las personas
for(int i = 0; i < listaPersonas.getCantidadPersonas(); i++){
Persona persona = listaPersonas.getPersonaI(i);
StdOut.println(persona.getApellido());
//StdOut.println(persona.toString());
}
}

}//fin clase ListaPersonasApp


2.72
2.6. Navegabilidad

2.6.1 Concepto de navegabilidad

Se pueden agregar flechas en los relacionamientos para indicar


navegabilidad.
1
Orden* Cliente
Compra

 A partir de la orden de compra, se puede conocer el cliente asociado.


 A partir de un cliente no se puede conocer las ordenes de compra que
tiene asociadas.

La responsabilidad no es simétrica, existe sólo resposabilidad a un lado de la


línea.

2.6.2. Implementación de asociaciones 1:1

1 1
A B

Ejemplo: Asociación entre Universidad y Rector.

A B

Ref. B. Ref. A.
2.73
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).

La aplicación debe realizar lo siguiente:


a) Ingresar un médico
b) Ingresar un paciente (sólo rut y nombre)
c) Ingresar el diagnóstico de un paciente
d) Asignar un médico a un paciente

Se pide: Modelo del dominio, diagrama de clases del dominio de la


aplicación y código

Modelo del dominio


atiende *
1
Médico Paciente
Rut Rut
Nombre Nombre
Registro médico Diagnóstico
especialidad

Diagrama de Clases del dominio de la aplicación


Medico Paciente
1 *
- String rut - String rut
- String nombre - String nombre
- String registroMedico - String disgnostico
- String especialidad - Medico medico
+ Paciente ()
+ Medico()
+ setDiagnostico()
+ get y set ….
+ getMedico(): Medico
+ toString(): String
+ setMedico()
+ toString(): String
2.74
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
}

public class Medico {


private String rut;
private String nombre;
private String registroMedico;
private String especialidad;
public Medico(String rut, String nombre, String registro, String especialidad){
this.rut = rut;
this.nombre = nombre;
this.registroMedico= registro;
this.especialidad = especialidad;
}
//get y set ….
//toString()…
} //Fin clase Medico

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.medico = null;
this.diagnostico = null;
}
2.75
public void setDiagnostico(String diagnostico){
this.diagnostico = diagnostico;
}
public void setMedico(Medico medico){ //asocia al medico
this.medico = medico;
}
public Medico getMedico (){
return this.medico;
}
//get y set …..
//toString() ….
} //Fin clase Paciente

public class App {


public static void main (String [ ] args) {
Medico m1 = new Medico(“111-k”, “Juan Perez”,
“151-5”, “cardiologo”);
Paciente p1 = new Paciente(“222-1”, “Pedro Soto”);
p1.setDiagnostico(“Apendicitis”);
p1.setMedico(m1);
}
}

Diagrama de Objetos

m1: Medico p1: Paciente

rut=111-k rut=222-1

nombre=Juan Perez nombre=Pedro Soto

registroMedico=151-5 diagnostico=Apendicitis

especialidad=cardiologo medico
2.76
2.6.3. Implementación de una asociación 1:N y/o N:N

Asociación 1: N
1 1..n
A B

Ejemplo: Asociación entre Departamento y Profesor.

A B

Conjunto Ref. A.
de ref.

Asociación N: N
1..n 1..n
A B

Ejemplo: Asociación entre Producto y Cliente.

A B

Conjunto Conjunto
Ref. B. Ref. A.

Para implementar estas asociaciones se usan los contenedores.


2.77
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:
 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 el
nombre del país y el nombre de cada una de sus ciudades.

Modelo del dominio


1 1..*
País Ciudad
Nombre Nombre
Idioma Alcalde
Cantidad de habitantes Cantidad de habitantes

Se debe navegar de país a sus ciudades


Diagrama de Clases del dominio de la aplicación
Ciudad
Pais 1 1 .. *

- String nombre El contenedor - String nombre


- String idioma necesario para - String alcalde
- int cantidadHabitantes la - int cantidadHabitantes
- Ciudad [ ] listaCiudades implementación
- int cantidadCiudades de la + Ciudad( )
navegabilidad + get y set….
+ Pais( ) se insertó en la + toString(): String
+ get y set …. clase Pais
+ getCantidadCiudades(): int
+ getCiudadI(i): Ciudad Métodos
+ ingresarCiudad(): boolean asociados al
+ toString(): String contenedor
2.78
Refino de la solución
main( ) {
Crear el objeto país (p)
Leer N
for i = 1 to N
Crear el objeto ciudad (c)
Asociar el objeto ciudad al objeto país (de país a ciudad)
end for
“Desplegar el nombre del país y el nombre de sus ciudades”
}

“Desplegar el nombre del país y sus ciudades”


desplegar nombre del país
Obtener la cantidad de ciudades del país (N)
Para cada ciudad (for I = 0 to N – 1):
Obtener la ciudad
obtener su nombre
desplegar el nombre

public class Ciudad {


private String nombre;
private String alcalde;
private int cantidadHabitantes;

public Ciudad (String nombre, String alcalde, int cantidadHabitantes) {


this.nombre = nombre;
this.alcalde= alcalde;
this.cantidadHabitantes = cantidadHabitantes;
}
public String getNombre ( ) {
return nombre;
}
//get y set …..
//toString()…
}
2.79
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;
this.listaCiudades = new Ciudad[max];
this.cantidadCiudades = 0;
this.max = max;
}

public boolean ingresarCiudad (Ciudad ciudad) {


if (cantidadCiudades < max) {
listaCiudades [cantCiudades] = ciudad;
cantidadCiudades ++;
return true;
}
return false;
}

public String getNombre ( ) {


return nombre;
}

public int getCantidadCiudades( ) {


return cantidadCiudades;
}
2.80
public Ciudad getCiudadI (int i ) {
if (i >= 0 && i < cantidadCiudades){
return listaCiudades[i];
}
else{
return null;
}
}
//toString()
}//Fin clase Pais
Debieran haber subprogramas
(métodos estáticos de la App) para
le lectura y despliegue de los
datos
public class App {

public static void main(String [ ] args) {


StdOut.print(“Ingrese cantidad de ciudades de Chile”);
int cantidadCiudades = StdIn.readInt();

Pais pais = new Pais (“Chile”, “Español”,


18000000, cantidadCiudades);

for (int I = 1; I <= cantidadCiudades; I++) {


StdOut.print(“Ingrese nombre ciudad”);
String nombre = StdIn.readString();
StdOut.print(“Ingrese Alcalde”);
String alcalde = StdIn.readString();
StdOut.print(“Ingrese cantidad de habitantes”);
int cantidadHabitantes = StdIn.readInt();
Ciudad ciudad = new Ciudad(nombre, alcalde, cantidadHabitantes);
pais.ingresarCiudad(ciudad);
}
2.81
// Desplegar datos en pantalla del país y sus ciudades
System.out.println(pais.getNombre ( ));
cantidadCiudades = pais.getCantidadCiudades();
for (i = 0; i < cantidadCiudades ; i++) {
Ciudad ciudad = pais.getCiudadI(i);
StdOut.println(ciudad.getNombreC( );
}
}
}
Se podría desplegar la información del pais
y sus ciudades, mediante el método to String()

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.82
Otra versión del mismo problema
Diagrama de Clases del dominio de la aplicación

Pais Ciudad

- String nombre
- String nombre
- String alcalde
- String idioma -int cantidadHabitantes
- int cantidadHabitantes
- ListaCiudades listaCiudades + Ciudad( )
+ get y set()…
+ Pais( )
+ toString(): String
+ get y set()….
+ getListaCiudades(): ListaCiudades *
+ toString(): String 1
ListaCiudades
- Ciudad [] lc
- int cantidadCiudades
- int max
public class Pais {
private String nombre; Objeto contenedor + ListaCiudades( )
+ getCantidadCiudades(): int
private String idioma;
+ insertarCiudad():boolean
private int cantidadHabitantes; + getCiudadI(i): Ciudad
private ListaCiudades listaCiudades; + toString(): String
public Pais (String nombre, String idioma, int cantidadHabitantes,
int max) {
this.nombre = nombre;
this.idioma= idioma;
this.cantidadHabitantes = cantidadHabitantes;
this.listaCiudades = new ListaCiudades(max);
}
public int getCantidadHabitantes() {
return this.cantidadHabitantes;
}
2.83
public String getIdioma() {
return this.idioma;
}
public String getNombre () {
return this.nombre;
}
public ListaCiudades getListaCiudades() {
return this.listaCiudades;
}
//toString()…..
}

public class Ciudad {


private String nombre;
private String alcalde;
private int cantidadHabitantes;

public Ciudad (String nombre, String alcalde, int cantidadHabitantes){


this.nombre = nombre;
this.alcalde= alcalde;
this.cantidadHabitantes = cantidadHabitantes;
}
public String getAlcalde() {
return this.alcalde;
}
public int getCantidadHabitantes() {
return this.cantidadHabitantes;
}
public String getNombre () {
return this.nombre;
}
//toString()….
}
2.84
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 cantCiudades;
}
public Ciudad getCiudadI(int i) {
if (i>= 0 && i < cantidadCiudades){
return lc[i];
}
else{
return null;
}
}
public boolean insertarCiudad(Ciudad ciudad) {
if (cantidadCiudades < max){
lc[cantidadCiudades] = ciudad;
cantidadCiudades ++;
return true ;
}
else{
return false ;
}
}
//toString()…
}
Debieran haber subprogramas (métodos estáticos 2.85
public class App { de la App) para le lectura y despliegue de los datos
public static void main(String[] args) {
StdOut.print ("Ingrese cantidad de ciudades de Chile");
int cantidadCiudades = StdIn.readInt();
Pais pais = new Pais ("Chile", "Español",
18000000, cantidadCiudades);
ListaCiudades listaCiudadesPais = pais.getListaCiudades();
for (int I = 1; I <= N; I++) {
StdOut.print("Ingrese nombre ciudad");
String nom = StdIn.readString();
StdOut.print("Ingrese Alcalde");
String alcalde = StdIn.readString();
StdOut.print("Ingrese cantidad de habitantes");
int cant = StdIn.readInt();
Ciudad ciudad = new Ciudad(nom, alcalde, cant);
listaCiudadesPais.insertarCiudad(ciudad);
//pais.getListaCiudades().insertarCiudad(ciudad);
}
// Desplegar datos en pantalla del país y sus ciudades
StdOut.println(pais.getNombre ( ));
listaCiudadesPais = pais.getListaCiudades();
cantidadCiudades = listaCiudadesPais.getCantidadCiudades();
for (int i = 0; i < N ; i++) {
Ciudad ciudad = listaCiudadesPais.getCiudadI(i);
StdOut.println(ciudad.getNombre ( ));
}
}//Fin main
} //Fin App Se podría tener:
StdOut.println(listaCiudadesPais.toString());
2.86
Modelo del dominio y diagrama de clases del dominio de la aplicación
asociado
Dado el modelo del dominio visto anteriormente, se muestra el diagrama de clases
asociado

1..* inscribe 1..*


Estudiante Asignatura

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.87
- Asignatura [] lista
Diagrama de clases - int max
+ ListaEstudiantes()
+ ingresar(): boolean
+ buscar(): Asignatura
+ eliminar(): boolean
+ getEstudianteI(int i): Estudiante
+ getCantidadEstudiantes(): int
+ setCantidadEstudiantes ():int
+ getMax(): int
+ setMax()

1 *
ListaInscripciones * Estudiante
Inscripcion 1 - String rut
- int cantidadInscripciones - int oportunidad
- Inscripcion [] lista - String nombre
- Asignatura asignatura - ListaInscripciones listaInscripciones
- int max - Estudiante estudiante
+ ListaInscripciones() + Estudiante()
+ Inscripcion() + getRut(): String
+ ingresar(): boolean + getOportunidad(): int
+ buscar(): Inscripcion + setRut()
+ setOportunidad() + getNombre(): String
+ eliminar(): boolean + getEstudiante(): Estudiante
+ getInscripcionI(int i): Inscripcion + setNombre ()
+ setEstudiante() + getListaInscripciones(): ListaInscripciones
+ getCantidadInscripciones(): int + getAsignatura(): Asignatura
+ setCantidadInscriciones() + setListaInscripciones()
+ setAsignatura()
+ getMax(): int
+ setMax() 1
1
Asignatura
ListaAsignaturas - String codigo
- int cantidadAsignaturas - String nombre
* - int creditos
- Asignatura [] lista
- int max - ListaInscripciones listaInscripciones
+ ListaAsignaturas() + Asignatura()
+ ingresar(): boolean + getCodigo(): String
+ buscar(): Asignatura + setCodigo()
+ eliminar(): boolean + getNombre(): String
+ getAsignaturaI(int i): Asignatura Se podrían tener el + setNombre ()
+ getCantidadAsignaturas(): int método toString() en + getCreditos(): int
+ setCantidadAsignaturas () + setCreditos()
+ getMax(): int cada una de las clases + getListaInscripciones(): ListaInscripciones
+ setMax() + setListaInscripciones()
2.88
2.7. Arquitectura de una aplicación

2.7.1. Contratos

 Luego de realizar el modelo de dominio, el siguiente paso es crear los


contratos.
 Para crear los contratos se deben identificar todas las operaciones del
sistema y asignar estas operaciones a las entidades correspondientes.
 Un contrato es una operación atómica del sistema, se hace o no se hace
 El diseño por contrato establece los derechos y responsabilidades para
cada elemento que conforma un sistema.
Los contratos son:
 Para el cliente, de manera
que él tenga claro lo que
hará su aplicación
 Para el diseñador y/o
programador
de manera de tener claro lo
que hace y no hace la
aplicación
 Un contrato define lo que se desea lograr con una operación
 Describe lo qué sucederá y no cómo.
 Definen los pre, post condiciones y aspectos invariantes del sistema.
 En un contrato no va la visibilidad
 Para cada operación del sistema se redacta un contrato.
2.89
Beneficio de los Contratos
 Mejora la documentación, lo que implica mejor calidad

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.90

Operación append(Collection c, Object o)


Descripción Agrega el objeto o a la colección c
Precondiciones Las variables c y o deben estar inicializadas, es decir, no deben
ser nulas. (c!=null && o != null)
Postcondiciones Se agrega el objeto o a la colección c.
El tamaño de c incrementa en 1.

Contratos Tutores
Operación Calcular horas()

Descripción Calcula el número de horas que tiene asignadas un


tutor
Precondiciones El tutor debe haber realizado al menos una actividad
de tutela.
Postcondiciones El valor resultante debe ser mayor o igual a 2.

Operación Calcular incentivo(horas)

Descripción Calcula el incentivo que se da al tutor, en función de


las horas asignadas
Precondiciones El mínimo valor de hora es 2.

Postcondiciones El valor resultante debe ser un entero positivo.


2.91
2.7.2. Interfaces para el diseño
 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.
2.92
Ejemplo: Interfaz Collection
interface Collection {
int MAXIMUN = 500;
void add(Object obj);
void delete(Object obj);
Object find(Object obj);
int currentCount (Object obj);
}

class FIFOQueue implements Collection {


……………
void add (Object obj) { Falta un arreglo o algo
-------------- para tener los elementos
de la colección
}
void delete (Object obj) {
--------------
}
Object find (Object obj) {
--------------
}
int currentCount (Object obj){
--------------
}
…………
}
2.93
 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.

 Polimorfismo en JAVA: Una variable declarada de una cierta interface,


puede mantener valores en cualquier clase, que implementa la interface.

Ejemplo

Diagrama de clases
<<interface>>
ListaAlumnos
+getElemento(): Alumno
+buscarElemento(): int
+insertarElemento(): boolean
+eliminarElemento(): boolean
+limpiar()
+isVacia():boolean
+getTamanio(): int

<<implements>>

ListaArregloEstatico * Alumno
- Alumno [] arreglo - int rut
- int posicionUltimoElemento - String nombre
- String apellido
- String direccion

….
2.94
public class Alumno {
private int rut;
private String nombre;
private String apellido;
private String direccion;
public Alumno() {
}
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 Alumno
2.95

/**
* Interface que representa el comportamiento de una lista de
* Alumnos. Esta puede ser implementada de la forma que se desee,
* es decir utilizando:
* - Arreglos estaticos:
* - Listas con nexo.
*/
public interface ListaAlumnos {

/**
* 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 Alumno/null
*/
public Alumno getElemento(int posicion);
2.96
/**
* 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(Alumno 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(Alumno elemento);

/**
* 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();
2.97
/**
* 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();

} //Fin interface ListaAlumnos

/**
* Clase que implementa la interface Lista que permite almacenar
* Alumnos
*/
public class ListaArregloEstatico implements ListaAlumnos {
private Alumno[] arreglo;
private int posicionUltimoElemento;

/**
* Constructor de la clase ListaArregloEstatico
* @param _capacidadMaxima : Cantidad maxima de elementos
* que puede almacenar esta lista.
*/
public ListaArregloEstatico(int capacidadMaxima) {
this.arreglo = new Alumno[capacidadMaxima];
this.posicionUltimoElemento = -1;
}
2.98
public Alumno getElemento(int posicion) {
if (posicion < 0 || posicion > this.arreglo.length) {
return null;
}
// Si no hay un dato en esa posicion
if (posicion > this.posicionUltimoElemento) {
return null;
}
return this.arreglo[posicion];
}

public int buscarElemento(Alumno elemento) {


// Recorro el arreglo tratando de encontrar el elemento
for (int i=0; i <= this.posicionUltimoElemento; i++) {
if (this.arreglo[i].getRut()==elemento.getRut()) {
return i;
}
}
// Si no lo encontre, retorno -1
return -1;
}

public boolean insertarElemento(Alumno elemento) {


// Si llegue justo a la capacidad maxima no puedo
// almacenar mas.
if (this.posicionUltimoElemento == arreglo.length-1) {
return false;
}
// Incremento el contador de elementos e ingreso el elemento.
this.posicionUltimoElemento++;
this.arreglo[this.posicionUltimoElemento] = elemento;
return true;
}
2.99
public void limpiar() {
int tamanio = this.arreglo.length;
this.arreglo = new Alumno[tamanio];
this.posicionUltimoElemento = -1;
}

public boolean isVacia() {


return (this.posicionUltimoElemento == -1);
}

public int getTamanio() {


return this.posicionUltimoElemento+1;
}

public boolean eliminarElemento(int posicion) {


// Si intento eliminar una posicion que no existe retorno falso
if (posicion < 0 || posicion > this.arreglo.length) {
return false;
}
// Si no hay un dato en esa posicion
if (posicion > this.posicionUltimoElemento) {
return false;
}
// Se procede a realizar el corrimiento para realizar la
// eliminacion
for (int i = posicion; i < this.posicionUltimoElemento; i++) {
this.arreglo[i] = this.arreglo[i+1];
}
this.posicionUltimoElemento--;
return true;
}
} //Fin class ListaArregloEstatico
2.100
public class TestLista {
public static void main(String[] args) {
// Lista que puede almacenar a lo mas 2 objetos.
ListaAlumnos lista = new ListaArregloEstatico(2);
Alumno alumno1 = new Alumno();
alumno1.setNombre("Javier");
alumno1.setApellido("Mandiola");
// inserto el alumno1 en la lista
if (lista.insertarElemento(alumno1)) {
StdOut.println("Alumno 1 insertado con exito");
}
else {
StdOut.println("Alumno 1 NO insertado");
}
Alumno alumno2 = new Alumno();
alumno2.setNombre("Claudio");
alumno2.setApellido("Vasquez");
// inserto el alumno2 en la lista
if (lista.insertarElemento(alumno2)) {
StdOut.println("Alumno 2 insertado con exito");
}
else {
StdOut.println("Alumno 2 NO insertado");
}
Alumno alumno3 = new Alumno();
alumno3.setNombre("Paul");
alumno3.setApellido("Beltrand");
2.101
// inserto el alumno3 en la lista, pero como la lista
//no tiene espacio esta operacion no es exitosa.
if (lista.insertarElemento(alumno3)) {
StdOut.println("Alumno 3 insertado con exito");
}
else {
StdOut.println("Alumno 3 NO insertado");
}

//Buscar al alumno 2
StdOut.println("Alumno 2 encontrado en posicion:" +
lista.buscarElemento(alumno2));

// Eliminacion de elementos en la lista


int k = 0;
if (lista.eliminarElemento(k)) {
StdOut.println("Alumno en posicion " + k +" eliminado!");
}
else {
StdOut.println("Alumno en posicion " + k + "No existe!!");
}

} //Fin main

}// Fin class TestLista


2.102
2.7.3. Implementación de contratos mediante interfaces

Ejemplo Calculadora
Se requiere implementar una calculadora con las 4 operaciones básicas.

Diagrama de
la Interfaz
2.103
Contratos en Java y su documentación
2.104
2.105
2.106
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 hará el sistema
 Un contrato se debe implementar en un método de la interface.
2.107
2.108
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

- $ int MAX_MONTO = 500


+ agregarAlumno(nombre: String, rut:
String, montoInicial: int): boolean

+ cargarMonedero(rut: String, clave: String,


monto: int): boolean

+ realizarCompra(rut: String, clave: String,


monto: int): boolean
2.109
/**
* Conjunto de funcionalidad que debe realizar
* el sistema.
* @author Diego P. Urrutia <[email protected]>
* @version 2014.03.20
*/

public interface BancoUCN {


/**
* Agrega un alumno al sistema con un saldo inicial.
* Restricciones:
* Que no exista el alumno.
*
* @param nombre del alumno.
* @param rut del alumno.
* @param montoInicial del monedero del alumno.
* @return true si fue posible agregar el alumno,
* falso en otro caso.
*/
public boolean agregarAlumno(String nombre,
String rut, String clave, int montoInicial);
2.110
/**
* Agrega un monto al monedero de un alumno.
* Restricciones:
* Que exista el alumno
*
* @param rut del alumno.
* @param monto de ucn a agregar al monedero.
* @return true si fue posible cargar el monedero.
*/
public boolean cargarMonedero(String rut,
String claveint monto);

/**
* 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.111
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
*/

public class BancoUCNImpl implements BancoUCN {

private ListaAlumnos listaAlumnos;

/**
* @see BancoUCN#agregarAlumno
*/
public boolean agregarAlumno(String nombre,
String rut, String clave, int montoInicial) {
………
2.112
Diagrama de Clases

- $ MAX_MONTO =500

<<implements>>

1 ListaAlumnos * Alumno
- ListaAlumnos listaAlumno …
….

)
2.113

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
2.114
2.7.4. Modularización de la aplicación mediante paquetes

¡Las clases no andan sueltas, se agrupan en paquetes!

Los paquetes contienen en su interior definiciones de una o más clases


lógicamente relacionadas.

Es una forma de modularizar los programas en JAVA.

El paquete es una colección de clases que se encuentran en el mismo


directorio.

Forma general de un archivo fuente de Java:


 Una única sentencia de paquete (opcional).
 Las sentencias de importación deseadas (opcional).
 Una única declaración de clase pública.
 Las clases privadas dentro del paquete que se requieran (opcional).

Formato general de la sentencia package es:


package paq1 [.paq 2[.paq 3]];

Un paquete declarado como:


package java.awt.imagen;

se debe almacenar en:


java\ awt\imagen (Windows)
ó
java/ awt /imagen (UNIX)

Si no se especifica ningún paquete, la clase se incorpora al paquete por


omisión, también conocido como el paquete innominado, pues carece de
nombre.
2.115
Todas las clases que se encuentran en archivos de un mismo directorio
forman un mismo paquete.

Los paquetes se organizan a su vez en una jerarquía de paquetes.

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.

Los paquetes se almacenan de una manera jerárquica y se importan


explícitamente, en las definiciones de clases nuevas

Ejemplo de Jerarquía de paquetes


Paquete
por P
omisión

A. java B. java B. java C. java R

Paquetes:
Paquete por omisión.
Paquete P
Paquete R
D. java
 El paquete P contiene las clases P.B y P.C.
 El paquete P.R contiene la clase P.R.D.
 Las clases A y B, se accesan directamente.
2.116
¿Cómo se organiza un proyecto en los paquetes?
.dominio
 Las clases de los
objetos del dominio.
Por ejemplo, Persona,
Alumno, etc.
 La clase comparador
(es interna a Persona)

.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

Recuerde que si el código de un paquete referencia al


código que está en otro paquete, se debe hacer el import
correspondiente
2.117
2.7.5. Ejemplos

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.

Modelo del dominio


Cuenta Bancaria
 saldo

Contratos

Operación Girar (cuenta bancaria, monto giro)


Descripción Se gira dinero desde la cuenta

Precondiciones Que exista la cuenta bancaria

Postcondiciones Saldo actualizado de la cuenta

Operación Depositar (cuenta bancaria, monto depósito)


Descripción Se deposita dinero en la cuenta
Precondiciones Que exista la cuenta bancaria

Postcondiciones Saldo actualizado de la cuenta


2.118
Operación Obtener datos cuenta bancaria
Descripción Se obtienen los datos de la cuenta
bancaria
Precondiciones Que exista la cuenta bancaria
Postcondiciones

Diagrama de clases del dominio de la aplicación

CuentaBancaria

- int saldo

+ CuentaBancaria()
+ girar(): boolean
+ depositar(): boolean
+ getSaldo(): int
+ setSaldo()
+ toString(): String
2.119
Diagrama de clases

<<interface>>
SistemaCuentaBancaria

+ depositar()
+ girar()
+ obtener DatosCuentaBancaria(): String

<<implements>> tiene

CuentaBancaria
SistemaCuentaBancariaImpl 1

- CuentaBancaria cuentaBancaria - int saldo


+ CuentaBancaria()
+ girar(): boolean
+ depositar(): boolean
+ getSaldo(): int
+ setSaldo()
+ toString(): String
1

o
1
2.120

/**
* © 2016 Escuela Ingenieria, UCN
*/
package cl.ucn.ei.pa.proyectocuentabancaria.dominio;

/**
* @author Loreto Telgie
* @Version: 1 septiembre 2016
*
*/
public class CuentaBancaria {
private int saldo;

/**
* @return the saldo
*/
public final int getSaldo() { Una alternativa a
return saldo; tener la lógica de
}
la aplicación en una
/** clase del dominio, es
* @param saldo the saldo to set tenerla en la clase
*/
public final void setSaldo(int saldo){ que implementa la
this.saldo = saldo; interfaz.
} Lo anterior con la
/**
finalidad de que las
* @param saldo clases del dominio
*/ de la aplicación
public CuentaBancaria(int saldo) { tengan solo la rutina
this.saldo = saldo;
} constructora y los
get y set.
public boolean girar(int montoGiro){
if (montoGiro < saldo){
saldo = saldo - montoGiro;
return true;
}
else{
return false;
}
}
2.121

public void depositar (int montoDeposito){


saldo = saldo + montoDeposito;

/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override Toda clase tiene un método toString()
public String toString() {
return "CuentaBancaria [saldo=" + saldo + "]";
}

}//Fin CuentaBancaria

Que la cantidad a depositar


(montoDeposito) o la cantidad
que se gira (montoGiro) sea
mayor que 0 debe ser
chequeado en la App.

Ahí se validan los datos de


entrada
2.122

/**
* © 2016 Escuela Ingenieria, UCN
*/
package cl.ucn.ei.pa.proyectocuentabancaria.logica;

/**
* @author Loreto Telgie
* @Version: 1 Septiembre 2016
*
*/

public interface SistemaCuentaBancaria {

/**
* @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.123

/**
* © 2016 Escuela Ingenieria, UCN
*/
package cl.ucn.ei.pa.proyectocuentabancaria.logica;

import cl.ucn.ei.pa.proyectocuentabancaria.dominio.CuentaBancaria;

/**
* @author Loreto Telgie
* @version: 1 septiembre 2016
*
*/
public class SistemaCuentaBancariaImpl implements
SistemaCuentaBancaria{
private CuentaBancaria cuentaBancaria; ;

public SistemaCuentaBancariaImpl(int saldoInicial) {


this.cuentaBancaria = new CuentaBancaria(saldoInicial);
}

Supuesto: El sistema cuando se


levanta crea el objeto cuenta bancaria,
es decir existe la cuenta
/**
* @see cl.ucn.ei.pa.proyectocuentabancaria.logica.
SistemaCuentaBancaria#depositar(int)
*/
public boolean depositar(int montoDeposito){
if (cuentaBancaria==null){
throw new NullPointerException("Cuenta bancaria
no existe para hacer un deposito");
}
else{
return cuentaBancaria.depositar(montoDeposito);
}
 Se trabaja con excepciones para implementar
} las precondiciones indicadas en los contratos
 Aquí se lanza la excepción

Aquí se podría tener la lógica del depositar


2.124

/**
* @see cl.ucn.ei.pa.proyectocuentabancaria.logica.
SistemaCuentaBancaria#girar(int)
*/
public boolean girar(int montoGiro){
if (cuentaBancaria==null){
throw new NullPointerException("Cuenta bancaria
no existe para hacer un giro");
}
else{
return cuentaBancaria.girar(montoGiro);
}
}
Aquí se podría
 Se trabaja con excepciones para implementar tener la lógica
las precondiciones indicadas en los contratos del girar
 Aquí se lanza la excepción
/**
* @see cl.ucn.ei.pa.proyectocuentabancaria.logica.
SistemaCuentaBancaria#obtenerDatosCuentaBancaria()
*/
public String obtenerDatosCuentaBancaria(){
if (cuentaBancaria==null){
throw new NullPointerException ("Cuenta bancaria
no existe");
}
return cuentaBancaria.toString();
}

}//Fin SistemaCuentaBancariaImpl
2.125

/**
* @author Loreto Telgie
* @version 1 septiembre 2016
*
*/
 En la App se leen los datos 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)
public static void main(String[] args) {

StdOut.print("Ingrese saldo inicial de la cuenta: ");


int saldo =StdIn.readInt();
//Debiera estar la validación de los datos de entrada

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 depositar debiera
validarse en la App
2.126

try{
sistema.girar(20);
}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{
StdOut.println("Datos cuenta bancaria " +
sistema.obtenerDatosCuentaBancaria());
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}

}//Fin main

} //Fin App

Diagrama de objetos
Si se ingresa como saldo inicial el
valor 100 cuentaBancaria: CuentaBancaria
saldo = 100
Se imprime 174
Saldo antes de las transacciones: 100
154
Antes de las transacciones: 154

Nota: En los talleres se debe trabajar con manejo de excepciones


2.127
Ejemplo 2
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).
La aplicación debe realizar lo siguiente:
a) Ingresar un médico
b) Ingresar un paciente (sólo rut y nombre)
c) Ingresar el diagnóstico de un paciente
d) Asignar un médico a un paciente
e) Desplegar al médico
f) Desplegar al paciente, incluyendo el nombre de su médico
Modelo del dominio
1 1..*
Médico Paciente
 rut atiende  rut
 nombre  nombre
 registro médico  diagnóstico
 especialidad

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.

Operación Ingresar paciente (rut, nombre)


Descripción Se ingresa un paciente
Precondiciones
Postcondiciones Paciente ingresado
2.128

Operación Asociar diagnóstico al paciente (diagnostico, rut paciente)


Descripción Se le asigna un diagnóstico al paciente
Precondiciones Que exista el paciente
Postcondiciones Diagnóstico asociado al paciente

Operación Asociar médico al paciente (rut paciente, rut medico)


Descripción Se le asigna un médico al paciente
Precondiciones  Que exista el médico
 Que exista el paciente

Postcondiciones Médico asignado al paciente

Operación Obtener datos del paciente y el de su médico (rut paciente)


Descripción Se obtiene los datos del paciente y los de su médico
Precondiciones Que exista el paciente
Postcondiciones

Operación Obtener datos del medico (rut medico)


Descripción Se obtiene los datos del médico
Precondiciones Que exista el médico
Postcondiciones
2.129
Diagrama de clases del dominio de la aplicación
Medico
- String rut
- String nombre
- String registroMedico
- String especialidad
+ Medico()
+ get y set ….
+ toString(): String
1

Paciente
- String rut
- String nombre
- String diagnostico
- Medico medico
+ Paciente ()
+ setDiagnostico()
+ getMedico(): Medico
+ setMedico()
+ get y set....
+ toString(): String
Diagrama de clases <<interface>> 2.130

SistemaMedico
Los métodos de la
interfaz corresponden + ingresarMedico(String rut, String nombre)
a los contratos. + ingresar Paciente(String rut, String nombre)
Un método por + asociarDiagnostico(String diagnostico, String rut)
contrato + asociarMedico(String rutPaciente, String rutMedico)
+ obtenerDatosMedico(String rutMedico):String
+ obtenerDatosPacienteYSuMedico(String rutPaciente):String

<<implements>>

Medico
- String rut
- String nombre
1
- String registroMedico
- String especialidad

o 1 1
+ Medico()
+ get y set ….
+ toString();

SistemaMedicoImpl
Paciente
- Medico medico - String rut
- Paciente paciente 1 - String nombre
- String diagnostico
- Medico medico
+ Paciente ()
+ setDiagnostico()
+ getMedico(): Medico
+ setMedico()
+ get y set...
+ toString(): String
2.131
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.132
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.133

package cl.ucn.ei.pa.sistemamedico.logica;
import cl.ucn.ei.pa.sistemamedico.dominio.*;
/**
* @author Loreto Telgie
*
*/
public interface SistemaMedico {

public void ingresarMedico(String rut, String nombre,


String registroMedico,String especialidad);
public void ingresarPaciente(String rut, String nombre);
public void asociarDiagnostico(String diagnostico, String rut);
public void asociarMedico(String rutPaciente, String rutMedico);

public String obtenerDatosMedico(String rutMedico);


public String obtenerDatosPacienteySuMedico(String rutPaciente);
}

package cl.ucn.ei.pa.sistemamedico.logica;
import cl.ucn.ei.pa.sistemamedico.dominio.*;

/**
* @author Loreto Telgie
*
*/
public class SistemaMedicoImpl implements SistemaMedico{

private Medico medico;


private Paciente paciente;
Cuando se levanta el
sistema no hay ningún
public SistemaMedicoImpl(){ paciente ni tampoco
medico= null;
paciente= null; un médico
}

public void ingresarMedico(String rut, String nombre,


String registroMedico,String especialidad){

Medico medico=new Medico(rut,nombre,registroMedico,


especialidad);
this.medico = medico;
}
2.134

public void ingresarPaciente(String rut, String nombre){


Paciente paciente = new Paciente (rut, nombre);
this.paciente = paciente;
}

public void asociarDiagnostico(String diagnostico, String rut){


if (paciente==null || !paciente.getRut().equals(rut)){
throw new NullPointerException ("Paciente no existe");
}
paciente.setDiagnostico(diagnostico);
}

public void asociarMedico(String rutPaciente, String rutMedico){


if (paciente==null || medico == null ||
!paciente.getRut().equals(rutPaciente) ||
!medico.getRut.equals(rutMedico)){
throw new NullPointerException ("Paciente y/o medico no existe");
}  Se trabaja con excepciones para
paciente.setMedico(medico); implementar las precondiciones
}
indicadas en los contratos
 Aquí se lanza la excepción
public String obtenerDatosMedico(String rutMedico){
if (medico==null || !medico.getRut.equals(rutMedico)){
throw new NullPointerException ("Medico no existe");
}
return medico.toString();
}

public String obtenerDatosPacienteySuMedico(String rutPaciente){


if (paciente==null || !paciente.getRut.equals(rutPaciente)){
throw new NullPointerException ("Paciente no existe");
}
return paciente.toString();
}

}
2.135

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
/**
* @author Loreto Telgie 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)
public static void main(String[] args) {
SistemaMedico sistema = new SistemaMedicoImpl();

String rutmedico= "111-K";


String nombre = "Juan Perez";
String registroMedico = "151-5";
String especialidad ="cardiologo";
//Debiera estar la validación de los datos de entrada

sistema.ingresarMedico(rutMedico,nombre,
registroMedico,especialidad);

String rutPaciente= "222-1";


nombre = "Pedro Soto";
//Debiera estar la validación de los datos de entrada

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.136

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

 Se trabaja con excepciones para


implementar las precondiciones indicadas
en los contratos

 Aquí se está capturando la excepción


2.137

Diagrama de Objetos

m1: Medico p1: Paciente

rut=111-k rut=222-1

nombre=Juan Perez nombre=Pedro Soto

registroMedico=151-5 diagnostico=Apendicitis

especialidad=cardiologo medico
2.138
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.

Modelo del dominio


Ciudad 0..* 1 Pais
 nombre pertenece
 nombre
 alcalde  idioma
 cantidad de habitantes  cantidad de habitantes

Contratos
Operación Ingresar un país (nombre, idioma, cantidad habitantes pais)
Descripción Se ingresa un país
Precondiciones
Postcondiciones País creado

Operación Ingresar ciudad de un pais (nombre, alcalde, cantidadHabitantes)


Descripción Se ingresa una ciudad, quedando asociada al país
Precondiciones Que exista el país
Postcondiciones Se crea la ciudad y se asocia con el pais
2.139

Operación Obtener datos del país y sus ciudades


Descripción Se obtienen los datos del país con sus ciudades
Precondiciones Que exista el país
Postcondiciones

Operación Obtener el país y sus ciudades


Descripción Se obtienen el país con sus ciudades
Precondiciones Que exista el país
Postcondiciones

La diferencia entre estos 2 últimos contratos es que:


 Obtener datos del pais y sus ciudades: Obtiene un string con todos los datos. Para
imprimir los datos basta con una impresión
 Obtener el pais y sus ciudades: Obtiene el objeto pais. Para imprimir se deben ir
sacando cada uno de los elementos del objeto país y luego desplegarlo

Usaremos la alternativa 1, de manera de no trabajar con objetos en la App

Versión 1
Diagrama de Clases del domino de la aplicación
1 0 .. *
Pais Ciudad
tiene
- String nombre
- String nombre
- String idioma
Un país podría - String alcalde
- int cantidadHabitantes
no tener - int cantidadHabitantes
- Ciudad [ ] listaCiudades
- int cantidadCiudades ciudades
+ Ciudad( )
+ Pais( ) + get y set….
+ get y set …. + toString():String
+ getCantidadCiudades(): int
+ getCiudadI(i): Ciudad
+ insertarCiudad():boolean
+ toString(): String
2.140
Diagrama de clases
<<interface>>
SistemaPaisCiudades
SistemaPaisCiudadesImpl
+ ingresarPais (nombre, idioma,
- Pais pais cantidadHabitantes)
+ obtenerDatosPaisCiudades(): String
+ obtenerPaisCiudades(): Pais
+ ingresarCiudadDeUnPais(nombre,
Uno de los 2 alcalde, cantidadHabitantes)
1
1 0 .. *
Pais Ciudad

- String nombre
- String nombre
- String idioma
- String alcalde
- int cantidadHabitantes
- int cantidadHabitantes
- Ciudad [ ] listaCiudades
- int cantidadCiudades
+ Ciudad( )
+ get y set….
+ Pais( )
+ toString(): String
+ get y set ….
+ getCantidadCiudades(): int
+ getCiudadI(i): Ciudad
+ insertarCiudad():boolean
+ toString(): String
2.141

package cl.ucn.ei.pa.paisciudades.dominio;

public class Ciudad {

private String nombre;


private String alcalde;
private int cantidadHabitantes;

public Ciudad(String nombre, String alcalde,


int cantidadHabitantes) {
this.nombre = nombre;
this.alcalde = alcalde;
this.cantidadHabitantes = cantidadHabitantes;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getAlcalde() {
return alcalde;
}
public void setAlcalde(String alcalde) {
this.alcalde = alcalde;
}
public int getCantidadHabitantes() {
return cantidadHabitantes;
}
public void setCantidadHabitantes(
int cantidadHabitantes) {
this.cantidadHabitantes = cantidadHabitantes;
}
2.142

public String toString() {


return "Ciudad [nombre=" + nombre + ", alcalde=" +
alcalde + ", cantidadHabitantes=" +
cantidadHabitantes + "]";
}
}

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.143

public final void setIdioma(String idioma) {


this.idioma = idioma;
}
public final int getCantidadHabitantes() {
return cantidadHabitantes;
}
public final void setCantidadHabitantes(
int cantidadHabitantes) {
this.cantidadHabitantes = cantidadHabitantes;
}
public void setCantidadCiudades(int
cantidadCiudades){
this.cantidadCiudades = cantidadCiudades;
}
public int getCantidadCiudades() {
return cantidadCiudades;
}
public boolean insertarCiudad(Ciudad ciudad) {
if (cantidadCiudades < max) {
listaCiudades[cantidadCiudades] = ciudad;
cantidadCiudades++;
return true;
} else {
return false;
}
}
public Ciudad getCiudadI(int i) {
if (i >= 0 && i < cantidadCiudades) {
return listaCiudades[i];
} else {
return null;
}
}
2.144

public String toString() {


String salida = "nombre pais= "+ nombre +
",idioma=" + idioma + ", cant habitantes="
+ cantidadHabitantes+ "Sus ciudades\n"
for(int i = 0; i < cantidadCiudades; i++){
salida=salida+listaCiudades[i].toString()+"\n";
}

return salida;
}
}

package cl.ucn.ei.pa.paisciudades.logica;

import cl.ucn.ei.pa.paisciudades.dominio.Pais;

public interface SistemaPaisCiudades {

public void ingresarPais(String nombre,


String idioma, int cantidadHabitantes,
int cantidadCiudades);

public void ingresarCiudadDeUnPais(String nombre,


String alcalde, int cantidadHabitantes);

public Pais obtenerPaisCiudades();

public String obtenerDatosPaisCiudades();

}
2.145
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;
}

public void ingresarPais(String nombre, String idioma,


int cantidadHabitantes, int cantidadCiudades) {

pais = new Pais(nombre, idioma,


cantidadHabitantes, cantidadCiudades);
}

public void ingresarCiudadDeUnPais(String nombre,


String alcalde, int cantidadHabitantes){
Ciudad ciudad = new Ciudad(nombre, alcalde,
cantidadHabitantes);
if (pais!= null){
pais.insertarCiudad(ciudad);
}
else{
throw new NullPointerException("No existe pais");
}
}
public Pais obtenerPaisCiudades() {
if (pais!= null){
return pais;
}
else{
throw new NullPointerException ("No existe pais");
}
}
2.146
public String obtenerDatosPaisCiudades(){
if (pais!= null){
return pais.toString();
}
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.*;
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 nombre = 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(nombre,
alcalde, cantidadHabitantes);
if (!ingreso){
StdOut.println("No hay espacio para ingresar ciudades");
}
} catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}
}
}
2.147

public static void desplegarPaisCiudades(Pais pais) {


StdOut.println("nombre pais: "+pais.getNombre() +
", idioma: " + pais.getIdioma() +
", cantidad habitanes: "
+ pais.getCantidadHabitantes());
for (int i = 0; i < pais.getCantidadCiudades();
i++){
Ciudad ciudad = pais.getCiudadI(i);
if (ciudad != null){
StdOut.println("ciudad " +
ciudad.getNombre()+ ", alcalde: " +
ciudad.getAlcalde()+ ", habitantes:" +
ciudad.getCantidadHabitantes());
}
}
}

public static void main(String[] args) {


SistemaPaisCiudades sistema = new
SistemaPaisCiudadesImpl();
LeerCiudadesPais(sistema);
try {
StdOut.println(sistema.
obtenerDatosPaisCiudades());

Pais pais = sistema.obtenerPaisCiudades();


App.desplegarPaisCiudades(pais);

} catch (NullPointerException ex) {


StdOut.println(ex.getMessage());
}
}//Fin main
}//Fin App
2.148
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.149
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( )
+ Pais( ) + get y set()…
+ get y set()…. + toString(): String
+ getListaCiudades(): ListaCiudades *
+ toString(): String
1
ListaCiudades
- Ciudad [] lc
- int cantidadCiudades
- int max
+ ListaCiudades( )
+ getCantidadCiudades(): int
+ insertarCiudad(): boolean
+ getCiudadI(i): Ciudad
+ toString(): String
2.150
Diagrama de clases

<<interface>>
SistemaPaisCiudades
SistemaPaisCiudadesImpl + ingresarPaisCiudades(nombre,
idioma, cantidadhabitantes)
- Pais p + ingresarCiudadDeUnPais (nombre,
alcalde, cantidadHabitantes)
+ obtenerDatosPaisCiudades(): String

Pais Ciudad
- String nombre - String nombre
- String idioma - String alcalde
- int cantidadHabitantes - int cantidadHabitantes
- ListaCiudades listaCiudades + Ciudad( )
+ Pais( ) + get y set()…
+ toString(): String
+ get y set()….
+ getListaCiudades(): ListaCiudades *
+ toString(): String
1
ListaCiudades
- Ciudad [] lc
- int cantidadCiudades
- int max
+ ListaCiudades( )
+ getCantidadCiudades(): int
+ insertarCiudad(): boolean
+ getCiudadI(i): Ciudad
+ toString(): String
2.151

package cl.ucn.ei.pa.paisciudades.dominio;

public class Ciudad {

private String nombre;


private String alcalde;
private int cantidadHabitantes;

public Ciudad(String nombre, String alcalde,


int cantidadHabitantes) {
this.nombre = nombre;
this.alcalde = alcalde;
this.cantidadHabitantes = cantidadHabitantes;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getAlcalde() {
return alcalde;
}
public void setAlcalde(String alcalde) {
this.alcalde = alcalde;
}
public int getCantidadHabitantes() {
return cantidadHabitantes;
}
public void setCantidadHabitantes(int cantidadHabitantes) {
this.cantidadHabitantes = cantidadHabitantes;
}
@Override
public String toString() {
return "Ciudad [nombre=" + nombre + ", alcalde=" +
alcalde + ", cantidadHabitantes=" +
cantidadHabitantes + "]";
}
}
2.152
package cl.ucn.ei.pa.paisciudades.dominio;
import cl.ucn.ei.pa.paisciudades.logica.ListaCiudades;
public class Pais {
private String nombre;
private String idioma;
private int cantidadHabitantes;
private ListaCiudades listaCiudades;
public Pais(String nombre, String idioma, int cantidadHabitantes,
cantidadCiudades){
this.nombre = nombre;
this.idioma = idioma;
this.cantidadHabitantes = cantidadHabitantes;
listaCiudades = new ListaCiudades(cantidadCiudades);
}
public final String getNombre() {
return nombre;
}
public final void setNombre(String nombre) {
this.nombre = nombre;
}
public final String getIdioma() {
return idioma;
}
public final void setIdioma(String idioma) {
this.idioma = idioma;
}
public final int getCantidadHabitantes() {
return cantidadHabitantes;
}
public final void setCantidadHabitantes(int cantidadHabitantes){
this.cantidadHabitantes = cantidadHabitantes;
}
public ListaCiudades getListaCiudades() {
return listaCiudades;
}
public String toString() {
String salida = "nombre pais= "+ nombre +
",idioma=" + idioma + ", cant habitantes="
+ cantidadHabitantes+ "Sus ciudades\n"
for(int i = 0; i < cantidadCiudades; i++){
salida=salida+listaCiudades.getCiudadI(i).toString()+"\n";
}
return salida;
}
}
2.153

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 getCiudadI(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.154

package cl.ucn.ei.pa.paisciudades.logica;

public interface SistemaPaisCiudades {

public void ingresarPais(String nombre, String idioma,


int cantidadHabitantes, int cantidadCiudades);

public boolean ingresarCiudadDeUnPais(String nombre,


String alcalde, int cantidadHabitantes);

public String obtenerDatosPaisCiudades();


}

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;
}

public void ingresarPais(String nombre, String idioma,


int cantidadHabitantes, int cantidadCiudades){
this.pais=new Pais(nombre,idioma,cantidadHabitantes,
cantidadCiudades);
}
2.155

public boolean ingresarCiudadDeUnPais(String nombre,


String alcalde, int cantidadHabitantes){
Ciudad ciudad = new Ciudad(nombre, alcalde,
cantidadHabitantes);
if (pais != null){
boolean ingreso =
pais.getListaCiudades().insertarCiudad(ciudad);
return ingreso;
}
else{
throw new NullPointerException ("No existe pais");
}
}

public String obtenerDatosPaisCiudades(){


if (pais != null){
return pais.toString();
}
else{
throw new NullPointerException ("No existe pais");
}
}
}
2.156

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();

boolean ingreso =
sistema.ingresarCiudadDeUnPais(nombre,
alcalde, cantidad);
if(!ingreso){
StdOut.println("No se ingreso ciudad.
No hay espacio");
}
}
}
2.157

public static void main(String[] args) {


SistemaPaisCiudades sistema=new SistemaPaisCiudadesImpl();
LeerCiudadesPais(sistema);

try {
StdOut.println(sistema.obtenerDatosPaisCiudades());
} catch (NullPointerException ex) {
StdOut.println(ex.getMessage());
}

}//Fin main

}//Fin App
2.158
Ejemplo 4

Se desea construir un programa que maneje información de países y de


ciudades. Un país está relacionado con varias ciudades; una ciudad está
relacionada con un único país.

Datos asociados a un país son:


 Nombre del país.
 Cantidad de habitantes.
 Idioma que se habla (sólo uno).
 Continente en que se encuentra.

Datos asociados a una ciudad son:


 Nombre de la ciudad.
 Cantidad de universidades que tiene la ciudad.
 Cantidad de museos que tiene la ciudad.

Se pide, un programa que haga:


a) Ingreso de datos de países y ciudades.
b) Dado el nombre del país, encontrar el nombre de las ciudades
relacionadas.
c) Cantidad de países europeos (Continente = “Europa”).
d) Indicar el nombre del país que tiene mayor cantidad de habitantes.
e) Dado el nombre de una ciudad encontrar los datos del país relacionado.

Modelo del dominio


1 1..*
País Ciudad
 Nombre tiene  Nombre
 Cantidad de habitantes  Cantidad de universidades
 Idioma  Cantidad de museos
 Continente
2.159
Contratos
Suponiendo que los datos se leen de la siguiente forma:
1°. Cantidad de países
2°. Por cada país los datos del país, incluyendo la cantidad de ciudades del
país
3°. Por cada ciudad del país, los datos de la ciudad
Los contratos associados al ingreso de los datos serían:
Operación Ingresar país (nombre, cantidad habitantes, idioma,
continente, cantidad de ciudades)
Descripción Se ingresa un país a la lista general de países

Precondiciones

Postcondiciones País ingresado a la lista general de países

Que exista espacio en el contenedor,


no es una precondición

Operación Ingresar ciudad (nombre, cantidad universidades, cantidad


museos)
Descripción Se ingresa una ciudad a la lista general de ciudades
Precondiciones

Postcondiciones Ciudad ingresada a la lista general de ciudades

Operación Asociar país ciudad(nombre pais, nombre ciudad)


Descripción Se asocia ciudad con país y el país con la ciudad
Precondiciones  Que exista el país
 Que exista la ciudad
Postcondiciones Asociaciones hechas entre país y ciudad:
 Ciudad ingresada a la lista de ciudades del país
 El país queda asociado como país de la ciudad
2.160
El resto de los contratos son:

Operación Encontrar ciudades de un país (nombre país)


Descripción Se obtienen los datos de las ciudades asociadas de un país

Precondiciones Que exista el país


Postcondiciones

Operación Obtener cantidad países europeos


Descripción Se obtiene la cantidad de países europeos
Precondiciones
Postcondiciones

Operación Obtener datos del país con más habitantes


Descripción Se obtienen los datos del país con la mayor cantidad de
habitantes

Precondiciones
Postcondiciones

Operación Encontrar el país de una ciudad (nombre ciudad)


Descripción Se obtiene los datos del país de una determinada ciudad

Precondiciones Que exista la ciudad


Postcondiciones
2.161
Diagrama de clases del domínio de la aplicación

1
Pais Ciudad
- String nombre - String nombre
- int cantidadHabitantes - int cantidadUniversidades
- String idioma - int cantidadMuseos
- String continente - Pais pais
- ListaCiudades listaCiudades + Ciudad()
+ Pais() + get y set …
+ get y set… + setPais()
+ getListaCiudades(): ListaCiudades + getPais(): Pais
+ setListaCiudades() + toString(): String
+ toString():String
*
*

1
ListaPaises ListaCiudades
- Pais [] lp - Ciudad [] lc
- int cantidadPaises - int cantidadCiudades
+ ListaPaises() - int max
+ ingresarPais(): boolean + ListaCiudades()
+ buscarPais(): Pais + ingresarCiudad():boolean
+ buscarCiudad(): Ciudad
+ getCantidadPaises(): int + getCantidadCiudades():int
+ getPaisI(): Pais + getCiudadI(): Ciudad
+ toString():String + toString():String
2.162
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
+ obtenerPaisMasHabitantes(): String
+encontrarPaisDeUnaCiudad(nomCiudad):String

1
Pais Ciudad
- String nombre
- String nombre
- int cantidadUniversidades
- int cantidadHabitantes
- int cantidadMuseos
- String idioma
- Pais pais
- String continente
- ListaCiudades listaCiudades + Ciudad()
+ get y set …
+ Pais() + setPais()
+ get y set… + getPais(): Pais
+ getListaCiudades(): ListaCiudades + toString():String
+ setListaCiudades()
+ toString(): String
*

*
1 1
ListaPaises ListaCiudades
- Pais [] lp - Ciudad [] lc
- int cantidadPaises - int cantidadCiudades
+ ListaPaises() - int max
+ ingresarPais(): boolean + ListaCiudades()
+ buscarPais(): Pais + ingresarCiudad():boolean
+ getCantidadPaises: int + buscarCiudad(): Ciudad
+ getPaisI(): Pais + getCantidadCiudades():int
+ getCiudadI();
+ toString(): String
+ toString(): String

1
2.163

package cl.ucn.ei.pa.sistemapaisesciudades.dominio;

public class Ciudad {


private String nombre;
private int cantidadUniversidades;
private int cantidadMuseos;
private Pais pais;

public Ciudad(String nombre, int cantidadUniversidades,


int cantidadMuseos) {
this.nombre = nombre;
this.cantidadUniversidades = cantidadUniversidades;
this.cantidadMuseos = cantidadMuseos;
pais = null;
}

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public int getCantidadUniversidades() {


return cantidadUniversidades;
}

public void setCantidadUniversidades(int cantidadUniversidades) {


this.cantidadUniversidades = cantidadUniversidades;
}

public int getCantidadMuseos() {


return cantidadMuseos;
}

public void setCantidadMuseos(int cantidadMuseos) {


this.cantidadMuseos = cantidadMuseos;
}
2.164

public Pais getPais() {


return pais;
}

public void setPais(Pais pais) {


this.pais = pais;
}

//@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;

public class Pais {


private String nombre;
private int cantidadHabitantes;
private String idioma;
private String continente;
private ListaCiudades listaCiudades;
private int cantidadCiudades;

public Pais(String nombre, int cantidadHabitantes, String idioma,


String continente, int cantidadCiudades) {
this.nombre = nombre;
this.cantidadHabitantes = cantidadHabitantes;
this.idioma = idioma;
this.continente = continente;
this.cantidadCiudades = cantidadCiudades;
listaCiudades = new ListaCiudades(cantidadCiudades);
}
2.165

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public int getCantidadHabitantes() {


return cantidadHabitantes;
}

public void setCantidadHabitantes(int cantidadHabitantes) {


this.cantidadHabitantes = cantidadHabitantes;
}

public String getIdioma() {


return idioma;
}

public void setIdioma(String idioma) {


this.idioma = idioma;
}

public String getContinente() {


return continente;
}

public void setContinente(String continente) {


this.continente = continente;
}

public ListaCiudades getListaCiudades() {


return listaCiudades;
}

public void setListaCiudades(ListaCiudades listaCiudades) {


this.listaCiudades = listaCiudades;
}
2.166

public String toString(){


String salida = nombre;
for (int i=0; i<listaCiudades.getCantidadCiudades(); i++){
salida = salida + listaCiudades.getCiudadI(i).toString();
}
return salida;
}

package cl.ucn.ei.pa.sistemapaisesciudades.logica;

import cl.ucn.ei.pa.sistemapaisesciudades.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 boolean ingresarCiudad(Ciudad ciudad){


if (cantidadCiudades < max){
lc[cantidadCiudades]= ciudad;
cantidadCiudades ++;
return true;
}
else{
return false;
}
}

public int getCantidadCiudades(){


return cantidadCiudades;
}
2.167
public Ciudad getCiudadI(int i){
if (i >=0 && i < cantidadCiudades){
return lc[i];
}
else{
return null;
}
}

public Ciudad buscarCiudad(String nombre){


int i;
for(i = 0; i < cantidadCiudades; i++){
if (lc[i].getNombre().equals(nombre)){
break;
}
}
if (i == cantidadCiudades){
return null;
}
else{
return lc[i];
}
}

public String toString() {


String salida = "";
for (int i = 0; i < cantidadCiudades; i++){
salida = salida + lc[i].toString();
}
return salida;
}

}
2.168
package cl.ucn.ei.pa.sistemapaisesciudades.logica;

import cl.ucn.ei.pa.sistemapaisesciudades.dominio.Pais;

public class ListaPaises {


private Pais []lp;
private int cantidadPaises;
private int max;

public ListaPaises(int max){


lp = new Pais [max];
cantidadPaises = 0;
this.max = max;
}

public boolean ingresarPais(Pais pais){


if (cantidadPaises < max){
lp[cantidadPaises]= pais;
cantidadPaises ++;
return true;
}
else{
return false;
}
}

public int getCantidadPaises(){


return cantidadPaises;
}

public Pais getPaisI(int i){


if (i >=0 && i < cantidadPaises){
return lp[i];
}
else{
return null;
}
}
2.169
public Pais buscarPais(String nombre){
int i;
for(i = 0; i < cantidadPaises; i++){
if (lp[i].getNombre().equals(nombre)){
break;
}
}
if (i == cantidadPaises){
return null;
}
else{
return lp[i];
}
}

public String toString() {


String salida = "";
for (int i = 0; i < cantidadPaises; i++){
salida = salida + lp[i].toString();
}
return salida;
}
}

package cl.ucn.ei.pa.sistemapaisesciudades.logica;

public interface SistemaPaisesCiudades {


public boolean ingresarPais(String nombre, int cantidadHabitantes,
String idioma, String continente, int cantidadCiudades);
public boolean ingresarCiudad(String nombre,
int cantidadUniversidades, int cantidadMuseos);
public void asociarPaisCiudad (String nombrePais,
String nombreCiudad);
public int obtenerCantidadPaisesEuropeos();
public String paisMasHabitantes();
public String paisDeterminadaCiudad(String nombreCiudad);
public String ciudadesDeterminadoPais(String nombrePais);
}
2.170
package cl.ucn.ei.pa.sistemapaisesciudades.logica;

import cl.ucn.ei.pa.sistemapaisesciudades.dominio.*;

public class SistemaPaisesCiudadesImpl implements SistemaPaisesCiudades{

private ListaPaises listaPaises;


private ListaCiudades listaCiudades;

public SistemaPaisesCiudadesImpl(int cantidadPaises) {


listaPaises = new ListaPaises(cantidadPaises);
listaCiudades = new ListaCiudades(1);
}

public boolean ingresarPais(String nombre, int cantidadHabitantes,


String idioma, String continente, int cantidadCiudades){
Pais pais = new Pais(nombre, cantidadHabitantes, idioma,
continente, cantidadCiudades);
boolean ingreso = listaPaises.ingresarPais(pais);
return ingreso;
}

public boolean ingresarCiudad(String nombre,


int cantidadUniversidades, int cantidadMuseos){
Ciudad ciudad = new Ciudad (nombre, cantidadUniversidades,
cantidadMuseos);
boolean ingreso = listaCiudades.ingresarCiudad(ciudad);
return ingreso;
}

public void asociarPaisCiudad (String nombrePais,


String nombreCiudad){
Pais pais = listaPaises.buscarPais(nombrePais);
Ciudad ciudad = listaCiudades.buscarCiudad(nombreCiudad);
if (pais != null && ciudad != null){
ciudad.setPais(pais);
boolean ingreso =
pais.getListaCiudades().ingresarCiudad(ciudad);
}
else{
throw new NullPointerException("No existe ciudad y/o pais");
}
}
2.171
public int obtenerCantidadPaisesEuropeos(){
int contadorPaisesEuropeos = 0;
for (int i = 0; i < listaPaises.getCantidadPaises(); i++){
if (listaPaises.getPaisI(i).getContinente().
equals("Europa")) {
contadorPaisesEuropeos++;
}
}
return contadorPaisesEuropeos;
}

public String paisMasHabitantes(){


int mayor = -1;
Pais paisMayor= null;
for (int i = 0; i < listaPaises.getCantidadPaises(); i++){
Pais pais = listaPaises.getPaisI(i);
if (pais.getCantidadHabitantes()> mayor) {
mayor = pais.getCantidadHabitantes();
paisMayor = pais;
}
}
if (paisMayor!= null){
return paisMayor.toString();
}
else {
return "no existe pais con mas habitantes";
}
}

public String paisDeterminadaCiudad(String nombre){


Ciudad ciudad = listaCiudades.buscarCiudad(nombre);
if (ciudad != null){
return ciudad.getPais().getNombre();
}
else{
throw new NullPointerException("No existe ciudad");
}
}
2.172
public String ciudadesDeterminadoPais(String nombrePais){
Pais pais = listaPaises.buscarPais(nombrePais);
if (pais != null){
return pais.getListaCiudades().toString();
}
else{
throw new NullPointerException("No existe el pais");
}
}

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;

public class App {

public static void main(String[] args) {


StdOut.print("Ingrese cantidad de paises: ");
int cantidadPaises = StdIn.readInt();
SistemaPaisesCiudades sistema =
new SistemaPaisesCiudadesImpl(cantidadPaises);

LeerPaisesCiudades(sistema, cantidadPaises);

int cantidad = sistema.obtenerCantidadPaisesEuropeos();


StdOut.println("Cantidad de paises europeos: "+ cantidad);

StdOut.println("Pais mas habitantes "+


sistema.paisMasHabitantes());

StdOut.print("nombre ciudad para buscar el pais asociado ");


String nombreCiudad = StdIn.readString();
2.173

try{
StdOut.println("Pais " +
sistema.paisDeterminadaCiudad(nombreCiudad));
} catch (IllegalArgumentException ex) {
StdOut.println(ex.getMessage());
}

StdOut.print("nombre pais para saber ciudades asociadas ");


String nombrePais = StdIn.readString();
try{
StdOut.println("Ciudades " +
sistema.ciudadesDeterminadoPais(nombrePais));
} catch (IllegalArgumentException ex) {
StdOut.println(ex.getMessage());
}
}

public static void LeerPaisesCiudades(SistemaPaisesCiudades sistema,


int cantidadPaises) {
for(int i = 0; i < cantidadPaises; i++){ //Por cada pais
StdOut.println("Ingrese datos de un pais ");
StdOut.print("Nombre pais: ");
String nombrePais = StdIn.readString();
StdOut.print("Idioma pais: ");
String idioma = StdIn.readString();
StdOut.print("Cantidad de habitantes pais ");
int cantidadHabitantes = StdIn.readInt();
StdOut.print("Ingrese continente: ");
String continente = StdIn.readString();
StdOut.print("Ingrese cantidad ciudades del pais " +
nombrePais);
int cantidadCiudades = StdIn.readInt();

boolean ingreso = sistema.ingresarPais(nombrePais,


cantidadHabitantes, idioma, continente,
cantidadCiudades);
2.174

//Se ingresa a la lista general de paises


if (!ingreso){
StdOut.println("No se ingreso el pais.
No hay espacio");
}
else{
for (int j = 0; j < cantidadCiudades ; j++){
//Para cada ciudad del pais
StdOut.println("Ingrese datos de una ciudad ");
StdOut.print("Nombre ciudad: ");
String nombreCiudad = StdIn.readString();
StdOut.print("Cantidad de universidades: ");
int cantidadUniversidades = StdIn.readInt();
StdOut.print("Cantidad de museos: ");
int cantidadMuseos = StdIn.readInt();

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(IllegalArgumentException ex){
StdOut.println(ex.getMessage());
}
}
}
}
}
}

}
2.175
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:

Operación Ingresar ciudad de un pais(nombre, cantidad


universidades, cantidad museos, nombre país)
Descripción  Se ingresa una ciudad a la lista de ciudades
 Se asocia la ciudad con el país:
 La ciudad se ingresa a la lista de ciudades del
país
 La ciudad queda asociada con el país
Precondiciones Que exista el país
Postcondiciones Ciudad ingresada en la lista de ciudades
Ciudad asociada con país
2
2.176
Código que cambia
package cl.ucn.ei.pa.sistemapaisesciudades.logica;

public interface SistemaPaisesCiudades {

public boolean ingresarPais(String nombre, int cantidadHabitantes,


String idioma, String continente);

public boolean ingresarCiudadDeUnPais(String nombre,


int cantidadUniversidades, int cantidadMuseos,
String nombrePais);

public int obtenerCantidadPaisesEuropeos();

public String paisMasHabitantes();

public String paisDeterminadaCiudad(String nombreCiudad);

public String ciudadesDeterminadoPais(String nombrePais);


}

Parte de Clase SistemaPaisesCiudadesImpl


public class SistemaPaisesCiudadesImpl implements
SistemaPaisesCiudades {
private ListaPaises listaPaises;
private ListaCiudades listaCiudades;
public SistemaPaisesCiudadesImpl(int cantidadPaises,
int cantidadCiudades) {
listaPaises = new ListaPaises(cantidadPaises);
listaCiudades = new ListaCiudades(cantidadCiudades);
}
2.177

public boolean ingresarPais(String nombre, int cantidadHabitantes,


String idioma, String continente){

Pais pais = new Pais(nombre, cantidadHabitantes, idioma,


continente);
boolean ingreso = listaPaises.ingresarPais(pais);
return ingreso;
}

public boolean ingresarCiudadDeUnPais(String nombre,


int cantidadUniversidades, int cantidadMuseos,
String nombrePais){

Pais pais = listaPaises.buscarPais(nombrePais);


if(pais== null){
throw new NullPointerException("No existe el pais");
}
Ciudad ciudad = new Ciudad (nombre, cantidadUniversidades,
cantidadMuseos);
boolean ingreso = listaCiudades.ingresarCiudad(ciudad);
ciudad.setPais(pais);
ingreso = pais.getListaCiudades().ingresarCiudad(ciudad);
return ingreso;
}
……

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.178

public static void LeerCiudades(SistemaPaisesCiudades sistema,


int cantidadCiudades){

for (int j = 0; j < cantidadCiudades ; j++){


//Para cada ciudad
StdOut.println("Ingrese datos de una ciudad ");
StdOut.print("Nombre ciudad: ");
String nombreCiudad = StdIn.readString();
StdOut.print("Cantidad de universidades: ");
int cantidadUniversidades = StdIn.readInt();
StdOut.print("Cantidad de museos: ");
int cantidadMuseos = StdIn.readInt();
StdOut.print("nombre del pais al que pertenece: ");
String nombrePaisPertenece = StdIn.readString();
try{
boolean ingreso =
sistema.ingresarCiudadDeUnPais(nombreCiudad,
cantidadUniversidades, cantidadMuseos,
nombrePaisPertenece);
//Se ingresa la ciudad a la lista de todas
//las ciudades
if(!ingreso){
StdOut.println("No se ingreso la ciudad.
No hay espacio");
}
}
catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}
}
}
2.179

public static void LeerPaises(SistemaPaisesCiudades sistema,


int cantidadPaises) {

for(int i = 0; i < cantidadPaises; i++){ //Por cada pais


StdOut.println("Ingrese datos de un pais ");
StdOut.print("Nombre pais: ");
String nombrePais = StdIn.readString();
StdOut.print("Idioma pais: ");
String idioma = StdIn.readString();
StdOut.print("Cantidad de habitantes pais ");
int cantidadHabitantes = StdIn.readInt();
StdOut.print("Ingrese continente: ");
String continente = StdIn.readString();

boolean ingreso= sistema.ingresarPais(nombrePais,


cantidadHabitantes, idioma, continente);
//Se ingresa a la lista general de paises
if(!ingreso){
StdOut.println("No se ingreso el pais.
No hay espacio");
}
}
}
2.180
2.8. Herencia en Java

2.8.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

Rectángulo Triángulo Círculo

Cuenta Bancaria

Cuenta Corriente Cuenta de Ahorro

Persona

Empleado Alumno

Ejemplo
Se tiene una jerarquía de clases, formada por una clase base (Persona) y dos
clases derivadas (Empleado y Alumno), junto a la correspondiente
definición de las propiedades, variables de instancia, y métodos, de cada
una de ellas.
Como las clases Empleado y Alumno heredan propiedades de la superclase
Persona, los objetos asociados a estas clases tienen las propiedades definidas
para la clase propiamente tal, y las heredadas de la clase Persona.
2.181
Superclase Persona, con subclase Alumno y Empleado

Persona

Alumno Empleado

Persona
Variables de instancia:
- nombre
- direccion
- fecha de nacimiento
Métodos:
- Inic-datos-persona
- Informa-datos-persona

Empleado Alumno
Variables de instancia: Variables de instancia:
- num-empleado - num-alumno
- sueldo - carrera
Métodos: Métodos:
- Inic-datos-empleado - Inic-datos-alumno
- Informa-sueldo - Informa-carrera

Se recomienda no más de 3 niveles


2.182
Herencia de propiedades en una jerarquía de clases

Empleado Empleado
Variables de instancia: Variables de instancia:
- num-empleado - nombre
- sueldo
- sueldo - direccion
- fecha-nacimiento
Métodos:
- Inic-datos-empleado - num_empleado
- Informa-sueldo Métodos:
- Inic-datos-persona
+ - Informa-datos-persona
PERSONA - Inic-datos-empleado
- Informa-sueldo

Alumno Alumno
Variables de instancia: Variables de instancia:
- num-alumno - nombre
- carrera - direccion
Métodos - fecha-nacimiento
- Inic-datos-alumno - num-alumno
- Informa-carrera - carrera
Métodos:
+ - Inic-datos-persona
PERSONA - Informa-datos-persona
- Inic-datos-alumno
- Informa-carrera

La habilidad de un lenguaje para soportar la herencia, distingue a los


lenguajes orientados al objeto, de los lenguajes basados en objetos.

Las reglas de herencia, permiten que un objeto de una subclase B puede


aparecer, donde quiera que un objeto de una superclase A es esperado.
2.183
Herencia simple: Hay una única superclase.

Herencia Múltiple: Hay varias superclases.

 ¡ JAVA tiene herencia simple !


 Smalltalk : Herencia Simple
 C++ : Herencia Múltiple
 Eiffel : Herencia Múltiple

Las reglas de herencia son:

 La herencia simple genera una jerarquía. En la raíz de la jerarquía se


encuentra la clase Object.

 Todas las clases, excepto la clase Object, tienen exactamente una


superclase.

 Una subclase hereda variables y métodos de su superclase.

 Una subclase puede declarar variables y métodos, diferentes de aquellos


heredados.

 Los métodos en la subclase, pueden redefinir a los métodos heredados


(“OVERRIDE”).

 Una variable heredada también se puede redefinir.


2.184
Ejemplo:
De la super clase los
public class Punto{ Punto atributos se colocan
- int x privados y los
private int x; - int y métodos pudieran ser
private int y; + Punto() protegidos

public Punto(int x, int y){ Podríamos colocar


this.x = x; los atributos como
this.y = y; protected, pero se
} Punto3D0 decide se colocarlos
- int z privados, porque
} + Punto3D0() para eso se tienen los
get y set.
class Punto3D0 extends Punto {
private int z;
La rutina constructora no se hereda
public Punto3D0(int x, int y, int z) {
super(x,y); //Se ejecuta la rutina contructora del padre
this.z = z; Si en vez de super (x,y), estuviera:
}  this.x = x;
 this.y = y;
public Punto3D0() { No compila:
this(-1, -1, -1);  Como x e y son privados no se pueden ver, aunque
} se hereden
}  Se requiere el super

protected Aunque la visibilidad fuese protected para los


La declaración es visible a atributos x e y, siempre se requiere invocar la rutina
la misma clase y a sus constructora del padre. Esto se hace a través del
subclases super en la rutina constructora del hijo
En JAVA, si la cláusula extends es omitida en la declaración de una clase,
ésta tendrá en forma implícita a la clase Object como su superclase
inmediata, que es la raíz de la jerarquía de clases de JAVA.
2.185
De esta manera, todas las clases son subclases directas o indirectas de la
clase Object.

Notación
La representación de la herencia, de acuerdo a la notación utilizada por
UML.
Superclase

Subclase1 Subclase2

Ejemplos:
Cuenta
Bancaria

Cuenta Cuenta
Ahorro Corriente
2.186

Equipo

Intercambiador
Bomba Estanque
de Calor

Estanque Estanque
.......
Esférico a Presión

Figura

Rectángulo Triángulo Círculo

Cuadrado
2.187
Mensajes a super

Cuando existe sobreescritura de métodos y/o atributos, la palabra super


permite tener acceso a los miembros públicos y protegidos (métodos y
atributos) de la clase padre.

Si quiero obtener un atributo sobreescrito privado de la clase padre, se usa


super.getAtributo()

Cuando una subclase sobrescribe un método heredado, el nombre especial


super, permite que el método sobrescrito sea usado, es decir usar el método
del padre.

Dentro de una subclase, un mensaje a super, invoca el método que la


superclase debería usar para ese mensaje.
2.188
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
} métodos get y set asociados . Los
public int getX(){ métodos pudieran ser protegidos
return x;
}
public int getY(){
return y;
}
}
2.189
public class Punto3D extends Punto {
private int z;

public Punto3D(int x, int y, int z) {


//llamado al constructor Punto(x,y)
super(x, y);
//Se invoca el método que la superclase debería usar
//para este mensaje
this.z = z;
}

public int getZ(){


return z;
}
}

public class Punto3DConstruct {


public static void main(String args[]) {
Punto3D p = new Punto3D(10, 20, 30);
StdOut.println("x = " + p.getX() + " y = " +
p.getY() + " z = " + p.getZ());
StdOut.println("p = " + p);
}
}

Resultado: x = 10 y = 20 z = 30
p = Punto3D @ 1cc807
Clase del Dirección
Objeto
2.190
public class A {
private int dato; A
- int dato
public A(int dato) {
+ A()
this.dato = dato; + m1(int x): int
} + get y set()…
public int getDato() {
StdOut.println("Pasa por getDato() del padre");
return dato;
} B
public void setDato(int dato) { - int dato
this.dato = dato;
} + B()
public int m1(int x) { + m1(int dato): int
StdOut.println("Pasa por m1 del padre"); + m2(): int
return x + 5; + get y set()…
}
}

public class B extends A{


private int dato;

public B(int dato, int dato1) {


super(dato);
this.dato = dato1;
}
public int getDato() {
StdOut.println("Pasa por getDato del hijo"); b:B
return dato; dato (heredado)=3
} dato (de B) = 2
public void setDato(int dato) {
this.dato = dato;
}
public int m1(int dato) {
StdOut.println("Pasa por m1 del hijo"); b
return super.m1(dato);//Invoca al m1 sobreescrito del padre
}
public int m2() { a
StdOut.println("Pasa por m2"); a:A
return super.m1(3) + super.getDato(); dato=5
//Invoca al m1 sobreescrito del padre y
//al dato sobreescrito del padre
}
}

public class App {


Se imprime
public static void main(String[] args) { Pasa por m1 del padre
A a = new A(5); a.m1(5)= 10
B b = new B(3,2); Pasa por m1 del hijo
Pasa por m1 del padre
StdOut.println("a.m1(5)= " + a.m1(5)); b.m1(2)= 7
Pasa por m2
StdOut.println("b.m1(2)= " + b.m1(2)); Pasa por m1 del padre
Pasa por getDato() del padre
StdOut.println("b.m2()= " + b.m2()); b.m2()= 11
}
}
2.191
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()
public double distancia + getX(): int
(int x, int y){ + getY(): int
StdOut.println("Primer método + distancia(int, int): double
distancia del padre Punto. + distancia (Punto): 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 ()
metodo distancia del padre + getZ(): int
Punto. Parametros: Punto"); + distancia(int, int, int): double
return this.distancia(p.x, p.y); + distancia(Punto3D): double
} + distancia(int, int): double
Si el objeto que invoca es de la clase Punto, se invoca el
primer método de distancia de la clase Punto.
Si el objeto que invoca es de la clase Punto3D, se invoca Redefinición
el tercer método de distancia de la clase Punto3D
}//Fin clase Punto
2.192
public class Punto3D extends Punto{
private int z;

public Punto3D(int x, int y, int z) {


super(x, y);
this.z = z; El super es necesario para
} invocar la rutina
constructora del padre
public int getZ(){
return z;
}

public double distancia(int x, int y,int z) {


System.out.println("Primer metodo distancia del hijo
Punto3D. Parametros: x, y, 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);
}

public double distancia(Punto3D otro) {


System.out.println("Segundo metodo distancia del hijo
Punto3D. Parametros: Punto3D");

return this.distancia(otro.getX(), otro.getY(), otro.z);


}
Si el objeto que invoca es de la clase Punto3D,
se invoca el primer método de distancia de la
clase Punto3D.
public double distancia(int x, int y) {
System.out.println("Tercer metodo distancia del hijo
Punto3D. Parametros: x, y");

double dx = (double)this.getX()/z -x;


double dy = (double)this.getY()/z -y;
return Math.sqrt(dx*dx + dy*dy);
}

}
2.193
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.194
Notas:
Hay una tensión importante, entre la herencia y el encapsulamiento.

El uso de la herencia expone alguno de los secretos de la clase


heredada.

En la práctica, esto significa que para comprender el significado de una


clase particular, a menudo se deben estudiar todas sus superclases,
incluyendo a veces su vista interna.

2.8.2. Selección de método dinámica (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.

Durante la ejecución, el objeto puede corresponder a alguna subclase del


objeto declarado. En este caso y cuando la subclase sobreescriba (redefina)
el método al que se llama, se utiliza la instancia real para decidir a qué
método llamar.

Polimorfismo = “LATE BINDING”


(enlace tardío)

Polimorfismo en Java:

En Java todas las variables son polimórficas.

Una variable declarada de una cierta clase, puede mantener valores de


cualquiera de sus subclases.
2.195
Ejemplo: Dos clases tienen una relación subclase/superclase, con un
único método que se sobrescribe en la subclase.
A
+ callme()
public class A {
public void callme() {
StdOut.println("Inside A's callme method"); B
} + callme()
}

public class B extends A{


El objeto corresponde al
public void callme(){
de la subclase. Recuerde
StdOut.println("Inside B's callme method");
que la regla de herencia
}
dice que un objeto de
}
una subclase B puede
aparecer donde quiera
public class Dispatch {
que un objeto de una
public static void main(String args[]) {
superclase A es
A a = new B(); //a pertenece a la clase A.
esperado
// Se ha almacenado una referencia a una
//instancia de la clase B en ella.
a.callme(); //invoca a callme de la clase B.
} Callme tiene que estar
} declarado en la clase A.
Resultado Esto se chequea en
Inside B’s callme method tiempo de compilación

El polimorfismo, es uno de los mecanismos más poderosos que ofrece la


orientación al objeto, para soportar la reutilización del código y la
robustez.

El ambiente de programación, proporciona un gran número de clases, las


que pueden ser adaptadas, mediante la herencia, a las necesidades de una
aplicación en particular.
Cambios en el main para ejercicio de la clase padre Punto y clase hija Punto3D
2.196
…..
Punto3D p2 = new Punto3D(0, 0, 0);
Punto p4 = new Punto3D(40, 50, 60);//Cumple la regla de herencia
Punto3D p5 = (Punto3D) p4;
StdOut.println("p2="+p2.getX()+ ", "+p2.getY()+", "+ p2.getZ());
StdOut.println("p4 = " + p4.getX() + ", " + p4.getY());
//No se puede desplegar z en p4
StdOut.println("p5="+p5.getX()+", "+p5.getY()+", "+p5.getZ());
StdOut.println("------------------------------"
En tiempo de compilación se chequea que distancia(Punto3D) esté definido en la clase Punto, ya que la declaración de p4 es
Punto. Esto se cumple, porque en la clase Punto está el método distancia(Punto). Se debe considerar que un objeto de la clase
Punto3D también es un objeto de la clase Punto.
En tiempo de ejecución se ejecuta el segundo método distancia de la clase Punto, distancia(Punto), el cual invoca a
this.distancia(int, int). Este último método está tanto en la clase Punto como en la clase Punto3D, está redefinido en Punto3D. Se
aplica el de la clase Punto3D, porque en tiempo de ejecución p4 es una instancia de Punto3D

StdOut.println("p4.distancia(p2) = "+ p4.distancia(p2));


StdOut.println("------------------------------");
En tiempo de compilación se chequea que distancia(Punto3D) esté definido en la clase Punto3D, ya que p5 es de la clase
Punto3D.
En tiempo de ejecución se ejecuta el segundo método distancia de la clase Punto3D, distancia(Punto3D), el cual invoca a
this.distancia(int, int, int). Este último método corresponde al primer método distancia de la clase Punto3D.

StdOut.println("p5.distancia(p2) = " + p5.distancia(p2));


StdOut.println("------------------------------"

StdOut.println("p5.distancia(1,1,2) = " + p5.distancia(1,1,2));

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.197
2.8.3. Clase abstracta
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.
Ejemplo:
Se desea construir una aplicación que manipula figuras (círculos, triángulos y rectángulos) en un
sistema gráfico, en base a las siguientes operaciones:
 Indicar ubicación de una figura.
 Dibujar una figura en el terminal. Para que una clase se defina como
 Imprimir una figura. abstracta debe tener al menos un método
 Rotar una figura. abstracto. Sino lo tiene, no necesita ser
 Indicar el color de una figura. abstracta
Las características del modelo orientado al objeto para definir clases y hacer explícitas las
propiedades comunes de las clases mediante el mecanismo de la herencia, permite obtener la
siguiente jerarquía de clases como solución al problema.
Figura
Clase Abstracta Figura
<<abstracta>>

Rectángulo Triángulo Círculo

Figura Rectángulo
Variables de instancia: Variables de instancia:
 Centro  Vértices
 Color
Métodos: Métodos:
 Ubicar  Dibujar
 Dibujar  Imprimir
 Imprimir  Rotar
Métodos Abstractos
 Rotar
 Color Circulo
Variables de instancia:
Triángulo
Variables de instancia:  Radio
 Limites
Métodos:
Métodos:
 Dibujar
 Dibujar
 Imprimir
 Imprimir
 Rotar
 Rotar
2.198
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 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.

Por ejemplo, si se desea incorporar la clase Cuadrado al sistema, sólo se


modifica la definición de clases anterior.
Figura

Rectángulo Triángulo Círculo

Rotar
Cuadrado Dibujar

La nueva clase sobrescribe los métodos Dibujar y Rotar, por


procedimientos específicos que se aplican solamente a las instancias de la
clase Cuadrado.
2.199
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.

Ejemplo: Se tiene una clase con un método abstracto, seguida de una


clase que implementa ese método.

public abstract class A { //clase abstracta


public abstract void callme(); //método abstracto A
<<abstract>>
public void metoo(){
StdOut.println("Inside A's metoo method"); + abs callme()
} + metoo()
}

public class B extends A {


public void callme(){ B
StdOut.println("Inside B's callme method");
} + callme()
}

public class Abstract {


public static void main(String args[]){
A a = new B();
a.callme(); //Se usa el del hijo, ya que el objeto es una
//instancia de la subclase
Resultado
a.metoo();
Inside B’s callme method
}
Inside A’s metoo method
}
2.200
Modificador final, para calificar una variable, método o clase

Por defecto todos los métodos y las variables de instancia, se pueden


sobrescribir.

En Java, si se desea declarar que ya no se quiere que las subclases


sobrescriban las variables o métodos, esto se puede declarar como final.

 Ejemplo para variables:

final int NUEVOARCHIVO= 1;

Por convención los nombres de los valores constantes están en


mayúscula.

 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.

public final class Integer

public final class Math


2.201
B)Ejemplos
Ejemplo 1: Cuenta bancaria
En un banco se manejan cuentas de ahorro y cuentas corrientes. Estos dos
tipos de cuenta son idénticos, excepto en las siguientes diferencias:
 Las cuentas de ahorro se numeran como 1xxxxx, empezando por 100001.
 Las cuentas corrientes se numeran como 5xxxx, empezando por 500001.
 Las cuentas de ahorro no tienen un cargo mensual (mantención), si el
saldo es superior a $200.000. Si no, se cobran $5.000 por mes. Las
cuentas corrientes pagan una cuota mensual de $5.000
 Las cuentas corrientes no pagan ningún interés, hasta que el saldo supera
los $500.000. A las cuentas de ahorro siempre se les paga interés.
 La aplicación muestra el resultado de ingresar $100.000 al mes, tanto en
una cuenta corriente como en una cuenta de ahorro a una cierta tasa de
interés anual. Esto se hace por 10 meses. Se debe chequear que la tasa de
interés esté entre 0 y 20.

Modelo del dominio


Cuenta de ahorro Cuenta corriente
número de cuenta número de cuenta
saldo saldo
tasa de interés tasa de interés

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.202

Operación Descontar mantención ()


Descripción Se descuenta al saldo de las 2 cuentas el valor de la mantención,
según corresponda
Precondiciones Que existan las 2 cuentas bancaria (la corriente y la de ahorro)
Postcondiciones Saldo actualizado de c/u de las cuentas

Operación Agregar interés (tasa de interés)


Descripción Se agrega al saldo de las 2 cuenta el monto asociado a los intereses,
según corresponda
Precondiciones Que existan las 2 cuentas bancaria (la corriente y la de ahorro)

Postcondiciones Saldo actualizado de c/u de las cuentas

Operación Chequear tasa de interés (tasa interés)

Descripción Se chequea que la tasa de interés esté entre 0 y 20


Precondiciones Que la tasa de interés esté entre 0 y 20 Esto es relativo,
ya que podría ser
Postcondiciones
considerado
como validación
de datos y no
Operación Obtener datos cuenta ahorro como una pre
Descripción Se obtienen los datos de la cuenta de ahorro condición

Precondiciones Que exista la cuenta de ahorro


Postcondiciones

Operación Obtener datos cuenta corriente

Descripción Se obtienen los datos de la cuenta corriente


Precondiciones Que exista la cuenta corriente
Postcondiciones
2.203
Diagrama de clases del dominio de la aplicación

CuentaBancaria
- double $ tasaInteres
- int saldo
El depositar y girar + CuentaBancaria()
podrían estar solo en + $ getTasaInteres(): double
la clase que + $ setTasaInteres()
implementa la + depositar(): int
interfaz, de manera + girar(): int
que la clase + getSaldo(): int
CuentaBancaria, + setSaldo()
quede solo con los get
y set

CuentaCorriente CuentaAhorro
- int $ corrNumero - int $ corrNumero
- int numeroCuenta - int numeroCuenta
+ CuentaCorriente() + CuentaAhorro()
+ getNumeroCuenta(): int + getNumeroCuenta(): int
2.204
Diagrama de clases CuentaBancaria
- double $ tasaInteres
- int saldo
+ CuentaBancaria()
+ $ getTasaInteres(): double
+ $ setTasaInteres()
+ depositar(): boolean
+ girar(): boolean
+ getSaldo(): int
+ setSaldo()

CuentaCorriente CuentaAhorro
- int $ corrNumero - int $ corrNumero
- int numeroCuenta - int numeroCuenta
+ CuentaCorriente() + CuentaAhorro()
+ get y set NumeroCuenta()… + get y set NumeroCuenta()…
+ $ getCorrNumero(): int + $ getCorrNumero(): int
+ $ setCorrNumero() + $ setCorrNumero()
1 1

SistemaCuentaCorrienteCuentaAhorroImpl
CuentaCorriente cuentaCorriente
CuentaAhoro cuentaAhorro

<<implements>>

SistemaCuentaCorrienteCuentaAhorro
<<interface>>
+ chequearTasaInteres(tasaInteres)
+ obtenerDatosCuentaCorriente(): String
+ obtenerDatosCuentaAhorro(): String
+ depositar(monto)
+ descontarMantencion()
+ agregarInteres(tasaInteres)
2.205

package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio;

public class CuentaBancaria {


private double saldo;
private static double tasaInteres;

public CuentaBancaria(double saldo) {


this.saldo = saldo;
}

public double getSaldo() {


return saldo;
}

public void setSaldo(double saldo) {


this.saldo = saldo;
}

public static double getTasaInteres() {


return tasaInteres;
}

public static void setTasaInteres(double tasaInteres) {


CuentaBancaria.tasaInteres = tasaInteres;
}

public void depositar(double montoDeposito){


saldo = saldo + montoDeposito;
}
2.206

public boolean girar(double montoGiro){


if (montoGiro < saldo){
saldo = saldo - montoGiro;
return true;
}
else{
return false;
}
}

@Override
public String toString() {
return "CuentaBancaria [saldo=" + saldo + "]";
}
}

package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio;

public class CuentaAhorro extends CuentaBancaria{


private int numeroCuenta ;
private static int correlativoNumeroCuenta = 100001;

public CuentaAhorro(int saldo) {


super(saldo);
numeroCuenta = correlativoNumeroCuenta;
//numeroCuenta = correlativoNumeroCuenta++;
correlativoNumeroCuenta++;
}

public int getNumeroCuenta() {


return numeroCuenta;
}

public void setNumeroCuenta(int numeroCuenta) {


this.numeroCuenta = numeroCuenta;
}
2.207

public static int getCorrelativoNumeroCuenta() {


return correlativoNumeroCuenta;
}

public static void setCorrelativoNumeroCuenta(


int correlativoNumeroCuenta) {
CuentaAhorro.correlativoNumeroCuenta=correlativoNumeroCuenta;
}

@Override
public String toString() {
return "CuentaAhorro [numeroCuenta=" + numeroCuenta +
", saldo=" + getSaldo() + "]";

package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio;

public class CuentaCorriente extends CuentaBancaria{


private int numeroCuenta ;
private static int correlativoNumeroCuenta = 500001;

public CuentaCorriente(int saldo) {


super(saldo);
numeroCuenta = correlativoNumeroCuenta;
//numeroCuenta = correlativoNumeroCuenta++;
correlativoNumeroCuenta++;
}

public int getNumeroCuenta() {


return numeroCuenta;
}

public void setNumeroCuenta(int numeroCuenta) {


this.numeroCuenta = numeroCuenta;
}
2.208

public static int getCorrelativoNumeroCuenta() {


return correlativoNumeroCuenta;
}

public static void setCorrelativoNumeroCuenta(


int correlativoNumeroCuenta) {
CuentaCorriente.correlativoNumeroCuenta =
correlativoNumeroCuenta;
}

@Override
public String toString() {
return "CuentaCorriente [numeroCuenta=" + numeroCuenta +
", saldo= "+ getSaldo()+"]" ;
}

package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.logica;

public interface SistemaCuentaCorrienteCuentaAhorro {

public void chequearTasaInteres(double tasaInteres);


public String obtenerDatosCuentaCorriente();
public String obtenerDatosCuentaAhorro() ;
public void depositar(int monto);
public void descontarMantencion();
public void agregarInteres();

}
2.209

package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.logica;

import cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.dominio.*;

public class SistemaCuentaCorrienteCuentaAhorroImpl implements


SistemaCuentaCorrienteCuentaAhorro{

private CuentaCorriente cuentaCorriente;


private CuentaAhorro cuentaAhorro;

public SistemaCuentaCorrienteCuentaAhorroImpl(){
//Cuando se levanta el sistema, se crean las
//2 cuentas con un saldo 0
cuentaAhorro = new CuentaAhorro(0);
cuentaCorriente = new CuentaCorriente(0);
}

public void chequearTasaInteres(double tasaInteres){


if (tasaInteres >=0.0 && tasaInteres <= 20.0){
CuentaBancaria.setTasaInteres(tasaInteres);
}
else{
throw new IllegalArgumentException(
"Tasa interes fuera de rango");
}
}

public String obtenerDatosCuentaCorriente(){


return cuentaCorriente.toString();
}

public String obtenerDatosCuentaAhorro() {


return cuentaAhorro.toString();
}
2.210
public void depositar(int monto){
if (cuentaCorriente != null && cuentaAhorro!= null ){
cuentaAhorro.depositar(monto);
cuentaCorriente.depositar(monto);
}
else{
throw new NullPointerException ("Cuenta no existe");
}
}

public void descontarMantencion(){


if (cuentaCorriente != null && cuentaAhorro!= null ){
cuentaCorriente.girar(5);
if (cuentaAhorro.getSaldo()<= 200){
cuentaAhorro.girar(5);
}
}
else{
throw new NullPointerException ("Cuenta no existe");
}
}

public void agregarInteres(){


if (cuentaCorriente != null && cuentaAhorro!= null ){
if (cuentaCorriente.getSaldo()>500000) {
cuentaCorriente.depositar((
CuentaBancaria.getTasaInteres()/12)
* cuentaCorriente.getSaldo());
}
cuentaAhorro.depositar((CuentaBancaria.getTasaInteres()/12) *
cuentaAhorro.getSaldo());
}
else{
throw new NullPointerException ("Cuenta no existe");
}
}
}
2.211

package cl.ucn.ei.pa.sistemacuentaahorrocuentacorriente.logica;

import ucn.StdIn;
import ucn.StdOut;

public class App {

public static void main(String[] args) {

SistemaCuentaCorrienteCuentaAhorro sistema =
new SistemaCuentaCorrienteCuentaAhorroImpl();

StdOut.print("Ingrese tasa de interes: ");


double tasaInteres = StdIn.readDouble();
try{
sistema.chequearTasaInteres(tasaInteres);
}catch(IllegalArgumentException ex){
StdOut.println(ex.getMessage());
}

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.212

//10 depositos de 100 c/u en las cuentas


for(int i = 1; i <= 10; i++){
try{
sistema.depositar(100);
sistema.descontarMantencion();
sistema.agregarInteres();

StdOut.println("datos cuenta corriente: + " +


sistema.obtenerDatosCuentaCorriente());
StdOut.println();
StdOut.println("datos cuenta ahorro: + " +
sistema.obtenerDatosCuentaAhorro());
StdOut.println();
}catch(NullPointerException ex1){
StdOut.println(ex1.getMessage());
}
}
}

}
2.213

Ejemplo 2: Vehículos
Construir un programa que maneje información de vehículos. Un vehículo
tiene un número de patente, marca y año de fabricación.

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.

La siguiente funcionalidad, mediante un menú, debe estar disponible para el


usuario del programa:

 Ingresar información de una cantidad indeterminada de autos y


camionetas (no se conoce la secuencia en que viene los datos; sí primero
un auto, luego un auto, luego una camioneta, etc.; la secuencia es
cualquiera)
 Listado de cada uno de los vehículos con sus datos asociados, en la
misma secuencia en que fueron ingresados.
 Dada la patente de un vehículo, se piden los datos de ese vehículo.
Además se pide el costo asociado por reparación. Si es camioneta el costo
es $100.000 por unidad de capacidad. Si es auto, es $20.000 por capacidad
del estanque.
 Cantidad total de vehículos, cantidad total de autos, cantidad total de
camionetas.
 Datos de la camioneta con la mayor 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.214
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

Operación Ingresar auto (patente, marca, año, kilómetros, capacidad


estanque)
Descripción Se ingresa un auto a la lista general de vehículos
Precondiciones
Postcondiciones Auto ingresado a la lista general de vehículos

Operación Obtener datos de todos los vehículos


Descripción Se obtienen los datos de todos los vehículos
Precondiciones
Postcondiciones
2.215

Operación Obtener datos de un vehículo, incluyendo su costo de


reparación (patente)
Descripción Se obtiene los datos del vehículo
Precondiciones Que exista el vehículo
Postcondiciones

Operación Obtener total de autos

Descripción Se obtiene la cantidad total de autos


Precondiciones
Postcondiciones

Operación Obtener total de camionetas


Descripción Se obtiene la cantidad total de camionetas
Precondiciones
Postcondiciones

Operación Obtener total de vehículos


Descripción Se obtiene la cantidad total de vehículos
Precondiciones
Postcondiciones
2.216

Operación Obtener datos de la camioneta con mayor capacidad de


carga
Descripción Se obtienen los datos de la camioneta con la mayor capacidad
de carga
Precondiciones
Postcondiciones

Diagrama de clases del dominio de la aplicación


ListaVehiculos * Vehículo
<< abstract>>
- Vehiculo [ ] lv - String patente
- int cantidadVehiculos - String marca
- int max - int agno
+ listaVehiculos() # Vehiculo()
+ ingresarVehiculo(): boolean + getMarca(): String
+ getCantidadVehiculos(): int + getAgno (): int
+ getVehiculoI(i): Vehiculo + getPatente(): String
+ buscarVehiculo(): Vehiculo + abs costoReparacion(): int
+ toString(): String + toString(): String

Camioneta Auto
- int capacidadCarga - int kilometraje
- int capacidadEstanque
+ Camioneta() + Auto()
+get y set ... + get y set ….
+ costoReparacion(): int + costoReparacion(): int
+ toString() + toString(): String
+
Recuerde que si una clase tiene un método
abstracto, tiene que ser abstracta. De hecho, sino
la define como abstracta arroja un error de
compilación
2.217
Diagrama de clases
Vehículo
ListaVehiculos * << abstract>>
- Vehiculo [ ] lv - String patente
- int cantidadVehiculos - String marca
- int max - int agno
# Vehiculo()
+ listaVehiculos()
+ getMarca(): String
+ ingresarVehiculo(): boolean + getAgno (): int
+ getCantidadVehiculos(): int + getPatente(): String
+ getVehiculoI(i): Vehiculo + abs costoReparacion(): int
+ buscarVehiculo(): Vehiculo + toString(): String
+ toString()
1 Camioneta Auto
- int capacidadCarga - int kilometraje
- int capacidadEstanque
+ Camioneta() + Auto()
+get y set ... + get y set ….
+ costoReparacion(): int + costoReparacion(): int
+ toString() + 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.218
package cl.ucn.ei.pa.sistemavehiculos.dominio;

public abstract class Vehiculo {


private String patente;
private String marca;
private int agno;

protected Vehiculo(String patente , String marca,


int agno) {
this.patente = patente;
this.marca = marca;
this.agno = agno;
}
public String getPatente() {
return (patente);
}
public String getMarca() {
return marca;
}
public int getAgno () {
return agno;
}
abstract public int costoReparacion();
//Método abstracto

@Override
public String toString() {
return "Vehiculo [" + (patente != null ?
"patente=" + patente + ", " : "")+
(marca != null ? "marca=" + marca + ", " : "")+
"agno=" + agno + "]";
}
}
2.219

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.220

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;
}

public int getCapacidadCarga() {


return capacidadCarga;
}

public int costoReparacion () {


return (capacidadCarga * 100000);
}

@Override
public String toString() {
return "patente: "+ getPatente() + " marca: "+
getMarca()+ " agno: " + getAgno()+ " Camioneta
[capacidadCarga=" + capacidadCarga + "]";
}

}
2.221

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;
}

//Ingresa un vehículo a la lista


public boolean ingresarVehiculo(Vehiculo v) {
if (cantidadVehiculos < max){
lv[cantidadVehiculos]= v;
cantidadVehiculos++;
return true;
}
else{
return false;
}
}
2.222

//Busca una patente de un vehículo en la lista


public Vehiculo buscarVehiculo(String patente) {
int j=0;
while (j < cantidadVehiculos &&
!lv[j].getPatente().equals(patente)){
j++;
}
if (j == cantidadVehiculos){
return null;
}
else{
return lv[j];
}
}

@Override
public String toString() {
String salida = "";
for(int i = 0; i < cantidadVehiculos; i++){
Vehiculo vehiculo = getVehiculoI(i);

if (vehiculo instanceof Camioneta) {


Camioneta camioneta = (Camioneta) vehiculo;
salida = salida + camioneta.toString();
}
else {
Auto auto = (Auto) vehiculo;
salida = salida + auto.toString();
}
salida = salida + " costo reparacion" +
vehiculo.costoReparacion()+ "\n";
}
return salida;
}
}
2.223

package cl.ucn.ei.pa.sistemavehiculos.logica;
import cl.ucn.ei.pa.sistemavehiculos.dominio.*;

public interface SistemaVehiculos {

public boolean ingresarAuto (String patente,


String marca, int año, int kilometros,
int capacidadEstanque);

public boolean ingresarCamioneta(String patente,


String marca,int año, int capacidadCarga);

public String obtenerDatosVehiculos();

public String obtenerDatosVehiculo (String patente);

public int obtenerTotalAutos();

public int obtenerTotalCamionetas();

public int obtenerTotalVehiculos();

public String obtenerDatosCamionetaMasCarga();

}
2.224

package cl.ucn.ei.pa.sistemavehiculos.logica;

import cl.ucn.ei.pa.sistemavehiculos.dominio.*;

public class SistemaVehiculosImpl implements


SistemaVehiculos{
private ListaVehiculos listaVehiculos;

public SistemaVehiculosImpl(){
listaVehiculos = new ListaVehiculos(10);
}

public boolean ingresarAuto(String patente, String marca,


int agno, int kilometros, int capacidadEstanque){

Vehiculo auto = new Auto (patente, marca, agno,


kilometros, capacidadEstanque);
boolean ingreso =
listaVehiculos.ingresarVehiculo(auto);
return ingreso;
}

public boolean ingresarCamioneta (String patente,


String marca, int año, int capacidadCarga){

Vehiculo camioneta = new Camioneta(patente, marca,


año, capacidadCarga);
boolean ingreso =
listaVehiculos.ingresarVehiculo(camioneta);

return ingreso;
}
2.225

public String obtenerDatosVehiculos(){


if (listaVehiculos!= null){
return listaVehiculos.toString();
}
else{
return null;
}
}

public String obtenerDatosVehiculo (String patente){


Vehiculo vehiculo =
listaVehiculos.buscarVehiculo(patente);
if (vehiculo !=null){
if (vehiculo instanceof Auto){
Auto auto = (Auto) vehiculo;
return auto.toString()+"costo reparacion: "
+ auto.costoReparacion();
}
else{
Camioneta camioneta=(Camioneta) vehiculo;
return camioneta.toString()+
"costo reparacion: " +
camioneta.costoReparacion();
}
}
throw new NullPointerException(
"No existe vehiculo");
}
2.226

public int obtenerTotalAutos(){


int cantidadAutos = 0;

for(int i=0;
i<listaVehiculos.getCantidadVehiculos();i++){

Vehiculo vehiculo =
listaVehiculos.getVehiculoI(i);

if (vehiculo instanceof Auto){


cantidadAutos++;
}
}
return cantidadAutos;
}

public int obtenerTotalCamionetas(){


int cantidadCamionetas = 0;
for(int i=0;
i< listaVehiculos.getCantidadVehiculos();i++){
Vehiculo vehiculo =
listaVehiculos.getVehiculoI(i);
if (vehiculo instanceof Camioneta){
cantidadCamionetas++;
}
}
return cantidadCamionetas;
}

public int obtenerTotalVehiculos(){


return listaVehiculos.getCantidadVehiculos();
//return (listaVehiculos.obtenerTotalCamionetas +
//listaVehiculos.obtenerTotalAutos);
}
2.227

public String obtenerDatosCamionetaMasCarga(){


int mayor= -1;
Camioneta camionetaMasCarga= null;
for(int i = 0;
i<listaVehiculos.getCantidadVehiculos();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.228

package cl.ucn.ei.pa.sistemavehiculos.logica;

import cl.ucn.ei.pa.sistemavehiculos.dominio.*;
import ucn.StdIn;
import ucn.StdOut;

public class App {

public static void leerUnVehiculo (SistemaVehiculos


sistema){
//Ingresa datos de un vehiculo
String patente,marca;
int kilometraje,capacidadEstanque,agno,tipo;
StdOut.print("Tipo vehiculo Auto[1] Camioneta[2]");
tipo = StdIn. readInt();
if (tipo == 1) {
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 el kilometraje=");
kilometraje = StdIn.readInt();
StdOut.print("Ingrese capacidad estanque = ");
capacidadEstanque = StdIn.readInt();
boolean ingreso =
sistema.ingresarAuto(patente, marca, agno,
kilometraje, capacidadEstanque);
if(!ingreso){
StdOut.println("No se hizo el ingreso del
auto. No hay espacio");
}
}
2.229

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");
}
}
}
}

public static void desplegarMenu(){


StdOut.println(" ");
StdOut.println(" M E N U");
StdOut.println("[1] Ingresar vehiculo ");
StdOut.println("[2] Listado de vehiculos ");
StdOut.println("[3] Buscar patente y desplegar
costo de reparacion");
StdOut.println("[4] Cantidad de vehiculos (autos
y camionetas) ");
StdOut.println("[5] Datos de la camioneta con la
mayor capacidad de carga ");
StdOut.println("[6] Salir ");
}
2.230
public static void menu(SistemaVehiculos sistema){
desplegarMenu();
StdOut.print("Ingrese opcion:");
int opcion = StdIn.readInt();
while(opcion != 6){
switch(opcion) {

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.231

case 4: int totalVehiculos =


sistema.obtenerTotalVehiculos();
StdOut.println("Total de vehiculos: " +
totalVehiculos);
int totalAutos= sistema.obtenerTotalAutos();
StdOut.println("Total autos: " + totalAutos);
int totalCamionetas =
sistema.obtenerTotalCamionetas();
StdOut.println("Total camionetas: " +
totalCamionetas);
break;
case 5:
//Muestra los datos de la camioneta con la
//mayor capacidad de carga

String datosCamioneta = sistema.


obtenerDatosCamionetaMasCarga()
if (datosCamioneta!= null) {
StdOut.println(datosCamioneta);
}
}
break;

} //fin switch
desplegarMenu();
StdOut.print("Ingrese opcion:");
opcion = StdIn.readInt();
}
}

public static void main(String[] args) {


SistemaVehiculos sistema =
new SistemaVehiculosImpl();
menu(sistema);
}
}
2.232
Concepto de Casting
Vehículo
Suponga la siguiente instrucción - String patente
- String marca
Java: - int agno
Vehiculo v = new Camioneta() # Vehículo()
+ m1()
: Camioneta + m2()

m1()
v m2() c
m3()
Camioneta Auto
-int capacidadCarga - int kilometraje
+ Camioneta() - int capacidadEstanque
+ m3() + Auto()
+ 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

Por lo tanto: √√Camioneta c = (Camioneta) v


2.233
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.234
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.235
Modelo del dominio
trabaja

Programador 1 1..5 Proyecto


 Rut  Nombre
1..5
 Nombre  Código
 Dirección  Duración en meses
 Sueldo base trabaja  Costo total
 Lenguaje de programación
 Horas extra 1..5
 Nivel de programador
1
Analista trabaja
 Rut
 Nombre
 Dirección
1
 Sueldo base
 Años de experiencia Ingeniero
 Rut
 Nombre
 Dirección
 Sueldo base
 Título
 Cantidad cargas familiares
2.236
Diagrama de clases del dominio de la aplicación
Funcionario
<<abstracta>>
- String rut
ListaFuncionarios
- String nombre - Funcionario [] lf
- String direccion * - int cantidadFuncionarios
- int sueldoBase - int max
- int tipo + ListaFuncionarios()
- ListaProyectos listaProyectos + ingresar(): boolean
+ buscar(): funcionario
+ getCantidadFuncionarios(): int
# Funcionario() + getFuncionarioI(i): Funcionario
# abs calcularSueldo(): int
+ getListadoProyectos(): ListaProyectos
+ get y set…()

Programador Analista
- String lenguaje - int anosExperiencia Ingeniero
- int horasExtras - int $ porcentajePorProyecto=25 - String titulo
- int nivel
- int $ porcentajePorProyecto=20 + Analista() - int cantidadCargas
+ calcularSueldo(): int - int $ porcentajePorProyecto=30
+ Programador()
+ calcularSueldo(): int + get y set… + Ingeniero()
+ get y set ….
+ calcularSueldo(): int
1 1 + get y set…
Proyecto
- int codigo
- int meses 1
- String nombre 1
- int monto
- Funcionario ingeniero ListaProyectos
- Funcionario analista
- Funcionario programador - Proyecto[] lp
+ Proyecto() * - int cantidadProyectos
+ getCodigo(): int
+ getNombre(): String + ListaProyectos()
+ getMonto(): int + ingresar(): boolean
+ getMeses(): int
+ setIngeniero() + buscar(): Proyecto
+ setAnalista() + getCantidadProyectos(): int
+ setProgramador() + getProyectoI(i): Proyecto
+ getIngeniero(): Funcionario
+ getAnalista(): Funcionario
+ getProgramador(): Funcionario
2.237
Contratos

Operación Ingresar proyecto (codigo, nombre, monto, meses)


Descripción Se ingresa un proyecto a la lista general de proyectos
Precondiciones
Postcondiciones Proyecto ingresado en la lista general de proyectos

Operación Ingresar analista (rut, nombre, dirección, sueldo base, años


experiencia)
Descripción Se ingresa un analista a la lista general de funcionarios
Precondiciones
Postcondiciones Analista ingresado a la lista general de funcionarios

Operación Ingresar programador (rut, nombre, dirección, sueldo base,


lenguaje programacion, horas extra, nivel programador)
Descripción Se ingresa un programador a la lista general de funcionarios
Precondiciones
Postcondiciones Programador ingresado a la lista general de funcionarios

Operación Ingresar ingeniero (rut, nombre, dirección, titulo, cargas)


Descripción Se ingresa un ingeniero a la lista general de funcionarios
Precondiciones
Postcondiciones Ingeniero ingresado a la lista general de funcionarios
2.238

Operación AsociarFuncionarioProyecto (codigo proyecto, rut)


Descripción Se asocia un funcionario al proyecto:
 El proyecto queda como parte de la lista de proyectos del
funcionario
 El proyecto queda asociado con el funcionario
Precondiciones  Que exista el proyecto
 Que exista el funcionario
Postcondiciones Proyecto con funcionario asociados

Operación Obtener datos de los proyectos


Descripción Se obtienen todos datos de los proyectos, incluido por cada
uno de ellos el costo total y mensual
Precondiciones
Postcondiciones

Operación Obtener datos de los funcionarios


Descripción Se obtienen todos los datos de los funcionarios, incluído el
sueldo
Precondiciones
Postcondiciones

Operación Obtener datos de los funcionario de un proyecto (código


proyecto)
Descripción Se obtienen los datos de los funcionarios asociados a un
proyecto
Precondiciones Que exista el proyecto
Postcondiciones
2.239

Operación Obtener datos proyectos de un funcionario (rut)


Descripción Se obtienen los datos de los proyectos asociados a un
funcionario
Precondiciones Que exista el funcionario
Postcondiciones

Operación Obtener datos de los ingenieros


Descripción Se obtienen los datos de los ingenieros
Precondiciones
Postcondiciones
2.240
Diagrama de clases
ListaFuncionarios ….. ListaProyectos
…. ….

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.241

package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;

import cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica.ListaProyectos;

public abstract class Funcionario { No vamos a usar el


private String rut; método toString() para
private String nombre;
private String direccion; ninguna de las clases
private int sueldoBase;
private int tipo;
private ListaProyectos listaProyectos;

protected Funcionario(String rut, String nombre, String direccion,


int sueldo, int tipo){
this.rut = rut;
this.nombre = nombre;
this.direccion = direccion;
this.sueldoBase = sueldo;
this.tipo = tipo;
listaProyectos = new ListaProyectos(5);
}

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 getDireccion() {
return direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
2.242
public int getSueldoBase() {
return sueldoBase;
}
public void setSueldoBase(int sueldoBase) {
this.sueldoBase = sueldoBase;
}
public int getTipo() {
return tipo;
}
public void setTipo(int tipo) {
this.tipo = tipo;
}

public ListaProyectos getListaProyectos() {


return listaProyectos;
}
public void setListaProyectos(ListaProyectos listaProyectos) {
this.listaProyectos = listaProyectos;
}

abstract public double calcularSueldo() ;


}

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;

private static int porcentajePorProyecto=20;

public Programador (String rut, String nombre, String direccion,


int sueldo, String lenguaje, int horasExtra, int nivel){
super (rut,nombre,direccion,sueldo,1);
this. lenguaje = lenguaje;
this. horasExtra = horasExtra;
this. nivel = nivel;
}
2.243
public String getLenguaje() {
return lenguaje;
}
public void setLenguaje(String lenguaje) {
this.lenguaje = lenguaje;
}
public int getHorasExtra() {
return horasExtra;
}
public void setHorasExtra(int horasExtra) {
this.horasExtra = horasExtra;
}
public int getNivel() {
return nivel;
}
public void setNivel(int nivel) {
this.nivel = nivel;
}
public double calcularSueldo(){
double suma = 0;
int monto;
double bono;
int meses;
ListaProyectos listaProyectos = this.getListaProyectos();
for (int i=0; i<listaProyectos.getCantidadProyectos();i++){
Proyecto proyecto = listaProyectos.getProyectoI(i);
monto = proyecto.getMonto();
meses = proyecto.getMeses();
bono=(monto/meses)*
(Programador.getPorcentajePorProyecto()/100);
suma = suma + bono;
}
double sueldo = this.getSueldoBase() +
5000*horasExtra+30000*nivel+suma;
return sueldo;
}
public static int getPorcentajePorProyecto() {
return porcentajePorProyecto;
}
public static void setPorcentajePorProyecto(int porcentajePorProyecto) {
Programador.porcentajePorProyecto = porcentajePorProyecto;
}
}
2.244
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica.ListaProyectos;
public class Analista extends Funcionario{
private int anosExperiencia;
private static int porcentajePorProyecto=25;

public Analista (String rut, String nombre, String direccion,


int sueldo, int anosExperiencia){
super(rut,nombre,direccion,sueldo,2);
this. anosExperiencia = anosExperiencia;
}
public int getAnosExperiencia() {
return anosExperiencia;
}
public void setAnosExperiencia(int anosExperiencia) {
this.anosExperiencia = anosExperiencia;
}
public double calcularSueldo(){
double suma = 0;
int monto;
double bono;
int meses;
ListaProyectos listaProyectos = this.getListaProyectos();
for (int i=0; i<listaProyectos.getCantidadProyectos();i++){
Proyecto proyecto = listaProyectos.getProyectoI(i);
monto = proyecto.getMonto();
meses = proyecto.getMeses();
bono=(monto/meses)*
(Analista.getPorcentajePorProyecto()/100);
suma = suma + bono;
}
double sueldo = this.getSueldoBase() + 5000 * anosExperiencia
+ suma;
return sueldo;
}
public static int getPorcentajePorProyecto() {
return porcentajePorProyecto;
}
public static void setPorcentajePorProyecto(int porcentajePorProyecto){
Analista.porcentajePorProyecto = porcentajePorProyecto;
}
}
2.245
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica.ListaProyectos;
public class Ingeniero extends Funcionario{
private String titulo;
private int cantidadCargas;
private static int porcentajePorProyecto=30;

public Ingeniero(String rut,String nombre, String direccion,


int sueldo, String titulo, int cantidadCargas){
super (rut,nombre,direccion,sueldo,3);
this. titulo = titulo;
this.cantidadCargas = cantidadCargas;
}

public double calcularSueldo(){


double suma = 0;
int monto;
double bono;
int meses;
ListaProyectos listaProyectos = this.getListaProyectos();
for (int i=0; i<listaProyectos.getCantidadProyectos();i++){
Proyecto proyecto = listaProyectos.getProyectoI(i);
monto = proyecto.getMonto();
meses = proyecto.getMeses();
bono=(monto/meses)*
(Ingeniero.getPorcentajePorProyecto()/100);
suma = suma + bono;
}
double sueldo = this.getSueldoBase() +
8000*this.cantidadCargas + suma;
return sueldo;
}

public String getTitulo() {


return titulo;
}
public int getCantidadCargas() {
return cantidadCargas;
}
2.246
public void setCantidadCargas(int cantidadCargas) {
this.cantidadCargas = cantidadCargas;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public static int getPorcentajePorProyecto() {
return porcentajePorProyecto;
}
public static void setPorcentajePorProyecto(int porcentajePorProyecto){
Ingeniero.porcentajePorProyecto = porcentajePorProyecto;
}

package cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio;

public class Proyecto {


private String codigo;
private String nombre;
private int monto;
private int meses;
private Funcionario ingeniero;
private Funcionario analista;
private Funcionario programador;

public Proyecto (String codigo,String nombre,int monto,int meses){


this.codigo = codigo;
this.nombre = nombre;
this.meses = meses;
this.monto = monto;
ingeniero =null;
analista = null;
programador = null;
}

public void setIngeniero (Funcionario ingeniero){


this.ingeniero = ingeniero;
}
public void setAnalista (Funcionario analista){
this.analista = analista;
}
2.247

public void setProgramador (Funcionario programador){


this. programador = programador;
}

public String getCodigo() {


return codigo;
}
public int getMonto() {
return monto;
}
public int getMeses() {
return meses;
}
public String getNombre() {
return nombre;
}
public Funcionario getIngeniero (){
return ingeniero;
}
public Funcionario getAnalista() {
return analista;
}
public Funcionario getProgramador() {
return programador;
}
public void setCodigo(String codigo) {
this.codigo = codigo;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public void setMonto(int monto) {
this.monto = monto;
}
public void setMeses(int meses) {
this.meses = meses;
}
}
2.248
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;
import cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio.Funcionario;
public class ListaFuncionarios {
private Funcionario []lf;
private int cantidadFuncionarios;
private int max;
public ListaFuncionarios(int max){
lf = new Funcionario [max];
cantidadFuncionarios = 0;
this.max = max;
}

public boolean ingresarFuncionario(Funcionario funcionario){


if (cantidadFuncionarios < max){
lf[cantidadFuncionarios]= funcionario;
cantidadFuncionarios ++;
return true;
}
else{
return false;
}
}

public int getCantidadFuncionarios(){


return cantidadFuncionarios;
}

public Funcionario getFuncionarioI(int i){


if (i >=0 && i < cantidadFuncionarios){
return lf[i];
}
else{
return null;
}
}
2.249

public Funcionario buscarFuncionario(String rut){


int i;
for(i = 0; i < cantidadFuncionarios; i++){
if (lf[i].getRut().equals(rut)){
break;
}
}
if (i == cantidadFuncionarios){
return null;
}
else{
return lf[i];
}
}
}

package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;

import cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio.Proyecto;

public class ListaProyectos {


private Proyecto []lp;
private int cantidadProyectos;
private int max;

public ListaProyectos(int max){


lp = new Proyecto [max];
cantidadProyectos = 0;
this.max = max;
}

public boolean ingresarProyecto(Proyecto Proyecto){


if (cantidadProyectos < max){
lp[cantidadProyectos]= Proyecto;
cantidadProyectos ++;
return true;
}
else{
return false;
}
}
2.250

public int getCantidadProyectos(){


return cantidadProyectos;
}

public Proyecto getProyectoI(int i){


if (i >=0 && i < cantidadProyectos){
return lp[i];
}
else{
return null;
}
}

public Proyecto buscarProyecto(String codigo){


int i;
for(i = 0; i < cantidadProyectos; i++){
if (lp[i].getCodigo().equals(codigo)){
break;
}
}
if (i == cantidadProyectos){
return null;
}
else{
return lp[i];
}
}
}
2.251

package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;

public interface SistemaFuncionariosProyectos {

public boolean ingresarAnalista(String rut,String nombre,


String direccion, int sueldoBase,int agnosExperiencia);

public boolean ingresarProgramador(String rut,String nombre,


String direccion, int sueldoBase, String lenguajeProgramacion,
int horasExtra, int nivelProgramador);

public boolean ingresarIngeniero(String rut, String nombre,


String direccion, int sueldoBase, String titulo,
int cantidadCargas);

public boolean ingresarProyecto(String codigo,String nombre,


int monto, int meses);

public void asociarFuncionarioProyecto (String codigoProyecto,


String rut);

public String obtenerDatosProyectos();

public String obtenerDatosFuncionarios();

public String obtenerDatosFuncionariosProyecto(String codigo);

public String obtenerDatosProyectosFuncionario(String rut);

public String obtenerDatosIngenieros();

}
2.252
package cl.ucn.ei.pa.sistemaFuncionariosProyectos.logica;

import cl.ucn.ei.pa.sistemaFuncionariosProyectos.dominio.*;

public class SistemaFuncionariosProyectosImpl implements


SistemaFuncionariosProyectos{
private ListaProyectos listaProyectos;
private ListaFuncionarios listaFuncionarios;

public SistemaFuncionariosProyectosImpl() {
this.listaProyectos = new ListaProyectos(6);
this.listaFuncionarios=new ListaFuncionarios(30);
}

public boolean ingresarAnalista(String rut,String nombre,


String direccion, int sueldoBase, int agnosExperiencia){

Funcionario elAnalista = new Analista (rut,nombre,direccion,


sueldoBase, agnosExperiencia);
boolean ingreso =
listaFuncionarios.ingresarFuncionario(elAnalista);
return ingreso;
}

public boolean ingresarProgramador(String rut, String nombre,


String direccion, int sueldoBase,
String lenguajeProgramacion, int horasExtra,
int nivelProgramador){

Funcionario elProgramador = new Programador (rut, nombre,


direccion, sueldoBase, lenguajeProgramacion,
horasExtra, nivelProgramador);
boolean ingreso =
listaFuncionarios.ingresarFuncionario(elProgramador);
return ingreso;
}
2.253

public boolean ingresarIngeniero(String rut,String nombre,


String direccion, int sueldoBase, String titulo,
int cantidadCargas){

Funcionario elIngeniero = new Ingeniero(rut,nombre,direccion,


sueldoBase, titulo, cantidadCargas);
boolean ingreso =
listaFuncionarios.ingresarFuncionario(elIngeniero);
return ingreso;
}

public boolean ingresarProyecto(String codigo,String nombre,


int monto, int meses){
Proyecto proyecto= new Proyecto(codigo, nombre,monto, meses);
boolean ingreso = listaProyectos.ingresarProyecto(proyecto);
return ingreso;
}

public void asociarFuncionarioProyecto (String codigoProyecto,


String rut){
Funcionario funcionario =
listaFuncionarios.buscarFuncionario(rut);
Proyecto proyecto =
listaProyectos.buscarProyecto(codigoProyecto);
if (funcionario != null && proyecto != null){
if (funcionario instanceof Analista){
proyecto.setAnalista(funcionario);
}
else{
if (funcionario instanceof Programador){
proyecto.setProgramador(funcionario);
}
else{
proyecto.setIngeniero(funcionario);
}
}
funcionario.getListaProyectos().ingresarProyecto(proyecto);
}
else{
throw new NullPointerException("No existe proyecto y/o funcionario");
}
}
2.254

public String obtenerDatosProyectos(){


String salida = "\nDatos de todos los proyectos\n";
for(int i = 0; i<listaProyectos.getCantidadProyectos();i++){

Proyecto proyecto = listaProyectos.getProyectoI(i);


salida = salida +"codigo: "+proyecto.getCodigo()+
", nombre: "+ proyecto.getNombre()+
", meses: " + proyecto.getMeses()+
", monto mensual: " +
proyecto.getMonto()/proyecto.getMeses()+
", monto total: "+ proyecto.getMonto()+ "\n";
}
return salida;
}

public String obtenerDatosFuncionarios(){


String salida = "\nListado de funcionarios\n";
for(int i = 0;
i<listaFuncionarios.getCantidadFuncionarios();i++){

Funcionario funcionario =
listaFuncionarios.getFuncionarioI(i);

salida = salida + "rut: "+funcionario.getRut()+


", nombre: "+ funcionario.getNombre()+
", direccion: "+funcionario.getDireccion()+
", sueldo base: "+funcionario.getSueldoBase()+
", sueldo: "+funcionario.calcularSueldo()+ "\n";
}
return salida;
}
2.255

public String obtenerDatosProyectosFuncionario (String rut){


String salida = "\nProyectos del funcionario "+rut+ "\n";
Funcionario funcionario = listaFuncionarios.buscarFuncionario(rut);
if (funcionario != null){
ListaProyectos listaProyectos =
funcionario.getListaProyectos();
for(int i=0; i<listaProyectos.getCantidadProyectos();i++){
Proyecto proyecto = listaProyectos.getProyectoI(i);
salida = salida + proyecto.getNombre() + "\n";
}
return salida;
}
else {
throw new NullPointerException(
"No existe el funcionario");
}
}

public String obtenerDatosIngenieros(){


String salida = "\nDatos de los ingenieros\n";
for(int i=0; i<listaFuncionarios.getCantidadFuncionarios();i++){
Funcionario funcionario =
listaFuncionarios.getFuncionarioI(i);
if (funcionario instanceof Ingeniero){
salida = salida + "nombre "+ funcionario.getNombre();
Ingeniero ingeniero = (Ingeniero) funcionario;
salida=salida+", titulo "+ingeniero.getTitulo()+"\n";
}
}
return salida;
}
2.256

public String obtenerDatosFuncionariosProyecto(String codigo){


String salida = "\nFuncionarios del proyecto "+codigo+ "\n";
Proyecto proyecto = listaProyectos.buscarProyecto(codigo);
if (proyecto == null) {
throw new NullPointerException("No existe el proyecto");
}
else {
if (proyecto.getIngeniero()!= null) {
salida = salida + "ingeniero "+
proyecto.getIngeniero().getNombre()+ "\n";
}
if(proyecto.getAnalista()!= null) {
salida = salida + "analista "+
proyecto.getAnalista().getNombre()+ "\n";
}
if (proyecto.getProgramador()!= null) {
salida = salida + "programador "+
proyecto.getProgramador().getNombre()+ "\n";
}
}
return salida;
}

}
2.257

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 {

public static void main(String[] args) throws IOException{


SistemaFuncionariosProyectos sistema =
new SistemaFuncionariosProyectosImpl();

leerProyectos(sistema);

leerFuncionarios(sistema);

leerPersonalProyectos(sistema);

StdOut.println(sistema.obtenerDatosProyectos());

StdOut.println(sistema.obtenerDatosFuncionarios());

StdOut.print("Rut funcionario para ver sus proyectos: ");


String rut = StdIn.readString();
try{
StdOut.println(sistema.obtenerDatosProyectosFuncionario(rut));
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}

StdOut.print("Codigo proyecto para ver sus funcionarios: ");


String codigo = StdIn.readString();
try{
StdOut.println(sistema.obtenerDatosFuncionariosProyecto(codigo));
}catch(NullPointerException ex){
StdOut.println(ex.getMessage());
}

StdOut.println(sistema.obtenerDatosIngenieros());
}
2.258

public static void leerFuncionarios(


SistemaFuncionariosProyectos sistema) throws IOException{
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.259

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");
}

public static void leerProyectos(


SistemaFuncionariosProyectos sistema) throws IOException{
ArchivoEntrada archivo = new ArchivoEntrada("Proyectos.txt");
boolean ingreso = true;
while(!archivo.isEndFile() && ingreso) {
Registro registro = archivo.getRegistro();
String nombre= registro.getString();
String codigo = registro.getString();
int duracion = registro.getInt();
int costo = registro.getInt();
ingreso=sistema.ingresarProyecto(codigo,nombre,costo,duracion);
if(!ingreso) {
StdOut.println("No hay espacio para mas");
}
}
archivo.close();
StdOut.println("Terminado de leer el archivo Proyectos");
}
2.260

public static void leerPersonalProyectos(


SistemaFuncionariosProyectos sistema) throws IOException{
ArchivoEntrada archivo =
new ArchivoEntrada("FuncionariosProyectos.txt");
while(!archivo.isEndFile()) {
Registro registro = archivo.getRegistro();
String codProyecto= registro.getString();
String rut= registro.getString();
sistema.asociarFuncionarioProyecto(codProyecto, rut);
}
archivo.close();
StdOut.println("Terminado de leer FuncionariosProyectos");
}

}
2.261
2.9. Visibilidad de clases y control de acceso para los miembros
de una clase

A) Visibilidad de clases

Al declarar una clase se puede especificar que es pública usando el atributo


public. De este modo la clase podrá ser usada por cualquier otra clase.

Si la clase no es pública, entonces la clase sólo puede ser usada dentro del
paquete que la contiene.

{public} {final / abstract} class...

Sólo se puede especificar uno de los atributos puestos en la misma llave.

B) Control de acceso para los miembros de una clase

Java soporta cuatro niveles de acceso para las variables y los métodos de una
clase:

 private
 protected
 public
 package (sin modificador)
2.262
Control de acceso para los miembros de una clase

Clase Subclase Package Mundo


Modificador:
private X
protected X X* X
public X X X X
package X X

PRIVADO:
Es el nivel de acceso más restrictivo. Un miembro privado es accesible sólo
en la clase en la que se encuentra definido.

Ejemplo: private

public class Alpha {


private int soyPrivado;

private void metodoPrivado() {


StdOut.println(“Método Privado”);
}
}

public class Beta{


void metodoAcceso() {
Alpha a = new Alpha();
a.soyPrivado = 10; //ilegal
a.metodoPrivado(); //ilegal
}
}
2.263
La clase Alpha contiene un método que compara el objeto actual (this)
con otro objeto de la misma clase:
public class Alpha {
private int soyPrivado;
boolean esIgualA(Alpha otraAlpha) {
if(this.soyPrivado == otraAlpha.soyPrivado){
return true;
}
else{
return false;
}
}

PROTECTED:
Permite que la clase, que las subclases, y que todas las clases en el mismo
paquete tengan acceso al miembro declarado como protegido.
Ejemplo: protected
package Greek;
public class Alpha {
protected int soyProtegido;
protected void metodoProtegido() {
StdOut.println(“Metodo protegido”);
}
}

package Greek;
public class Gamma {
void metodoAcceso() {
Alpha a = new Alpha();
a.soyProtegido = 10; //legal
a.metodoProtegido(); //legal
}
}
2.264
En el caso de una subclase A que reside en un paquete diferente, esta
subclase A puede referenciar los miembros protegidos de la clase B sólo en
el caso de aquellos objetos de la subclase A o de subclases de A.

import Greek.*;
package Latin;

public class Delta extends Alpha {


void metodoAcceso(Alpha a, Delta d) {
a.soyProtegido = 10; //ilegal
d.soyProtegido = 10; //legal
a.metodoProtegido(); //ilegal
d.metodoProtegido(); //legal
}
}

PUBLIC:
Cualquier clase en cualquier paquete, tiene acceso a los miembros públicos
de la clase.

Ejemplo: public

package Greek;

public class Alpha {


public int soyPublico;

public void metodoPublico() {


StdOut.println(“Método Público”);
}
}
2.265
import Greek.*;
package Roman;
public class Beta {
void metodoAcceso() {
Alpha a = new Alpha();
a.soyPublico = 10; //legal
a.metodoPublico(); //legal
}
}

PACKAGE:
Si un miembro de una clase no tiene modificador, entonces será visible a
todas las clases del mismo paquete. Esto es lo establecido por defecto.

Ejemplo: package
package Greek;
public class Alpha {
int soyUnPaquete;

void metodoPaquete() {
StdOut.println(“Método Paquete”);
}
}
package Greek
public class Beta {
void metodoAcceso() {
Alpha a = new Alpha();
a.soyUnPaquete = 10; //legal
a. metodoPaquete(); //legal
}
}
2.266
C) Resumen de los atributos que pueden tener variables
y métodos

VARIABLE:

{private / public / protected}

{final}

{static}

MÉTODO:

{private / public / protected}

{final / abstract}

{static}

Sólo se puede especificar uno de los atributos puestos en la misma llave.


2.267
Ejercicio
package P1;
import P2.C4;
public class C1{
private int a1;
protected int a2;
private void imprimir(){
StdOut.print("Valor: " + this.a1); La clase C4, aunque es
} pública, no es accesible
public int getA1(){ desde C1, ya que está
return this.a1; en otro paquete. Para
} usarla debería tener:
protected void setA1(int v){  import P2.C4;
this.a1 = v; ó
}  P2.C4 a
public void aumentarC4(C4 a){
C5 c = a.getC5();
La clase C5, aunque es
this.a1 = c.getA1(); pública, no es accesible
a.setA1(50*this.a1); desde C1, ya que está
} en otro paquete. Para
} usarla debería tener:
 import P2.C5;
package P1; ó
public class C2{  P2.C5 c = a.getC5();
protected int a1;
public final int a2 = 1000; La clase C4, aunque es
protected void imprimir(){ pública, no es accesible
StdOut.print("Valor: " + this.a1); desde C2, ya que está en
} otro paquete.
public int metodo1(C2 a, C4 b){ Para usarla debería tener:
return a.getA1() * b.a2;  import P2.C4;
} ó
 P2.C4 b
2.268
public int getA1(){
return this.a1;
}
}

package P1;

public final class C3{


private int a1;
private int a2;
public int a3;

private int calcular(C1 a, C2 b, C3 c){


a.a2 = a.a2*2;
b.a1 = b.a1+15; El atributo a1 de la
c.a1 = a.a1*b.a1; clase C1 es privado, por
lo tanto no lo puedo
return c.a1;
accesar.
}

public int metodo1(C2 a){


int base = this.a1 * 100;
int multiplicador = a.getA1();
int total = base * multiplicador;
if (total > 5000) { El atributo a2 de la
a.a2 = total; clase C2 es final, por
} lo tanto no puede
else { modificarse.
this.a2 = total;
}
return total;
}
}
2.269
package P2;
import P1.*; El atributo a2 de la clase
C1 no es visible, ya que es
public class C4 extends C1{ protected y para que se
private int a1; pueda usar debiera estar en
public int a2; el mismo paquete de la
private C5 a3; clase C4, lo que no es así.
De hecho la clase C4 está
private void metodo1(C1 a, C4 b){ en el paquete P2 y la clase
int temp = b.a2*5; C1 en el P1.
b.a1 = a.a2 * temp;
} Aunque se importó el
paquete P1, se debe
public C5 getC5(){ considerar el hecho de que
return a3; cuando residen en paquetes
} distintos, la subclase puede
referenciar los miembros
public void setA1(int v){ protected solo para los
this.a1 = v; objetos de la subclase o de
} susbsubclases.
} De hecho, a no es de la
subclase, es de la super
package P2; clase.
public class C5 extends C3{
private int a1; La clase C3 es final,
por lo tanto no se
private void imprimir(){ pueden definir
StdOut.print("Valor: " + this.a1); subclases desde C3.
}

public int get_a1(){


return this.a1;
}
}
2.270
Ejercicio
El siguiente código, ¿Tiene algún error?, ¿Cuál es?

public class Punto{


protected int x;
protected int y;

Punto(int x, int y){


this.x=x;
this.y=y;
}
public int getX(){
return x;
}
}

public class Punto3d extends Punto{


private int z;
Punto3d(int x,int y){
super(x,y);
}
public void setZ(int z){
this.z=z;
}
}

public class Principal{


public static void main (String[] args){
Punto miPunto=new Punto3d(30,50);
miPunto.setZ(40);
}
}
2.271
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.

Las Operaciones que los objetos realizan, resultan de:


 Consultas.
 Actualizaciones.
 Procesos sobre los datos.

Se deben identificar las entidades externas que interactuan con el sistema, y


las diferentes maneras en que usan el sistema.

 Agregar, eliminar y modificar alumno.


 Agregar, eliminar y modificar curso.
 Agregar, eliminar y modificar profesor.
 Agregar, eliminar estudiante de un curso.
 Asignar, modificar un profesor a un curso.
 Encontrar todos los alumnos de un curso.
 Encontrar todos los cursos que dicta un profesor.
2.272
B) Ejercicio: Declaración del problema

El programa debe manejar información relacionada con los empleados de la


empresa, y sus datos asociados. Para cada empleado se manejan datos de:
 Rut
 Nombre
 Dirección
 Fecha de contratación
 Teléfono particular

Los empleados están asignados a un único departamento. La empresa cuenta


con varios departamentos, para los que se tienen datos de:
 Código
 Nombre
 Localización

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.

Algunos empleados trabajan con contrato a plazo indefinido, fijándoseles un


sueldo base a pagar por mes. Estos empleados tienen fijada además, una
2.273
bonificación que asciende al 25% del sueldo base y un bono de
antigüedad, que varia para cada trabajador.

Algunos empleados pertenecen a uno de los varios sindicatos que funcionan


al interior de la empresa. Cada sindicato tiene un código, un nombre, un
teléfono, una dirección y fija un monto de cuota mensual a pagar por cada
uno de sus afiliados, para ser descontada de su remuneración. Sólo los
empleados con contrato a plazo indefinido, pueden pertenecer a un sindicato.

Se necesita:

1. Ingresar datos al programa.

2. Peticiones que el sistema debe responder:

 Dado un nombre de departamento, encontrar los nombres de sus


empleados.
 Dado un nombre de empleado, encontrar el nombre de su departamento.
 Dado un nombre de empleado, encontrar (si existe), el vehículo
asignado.
 Dado un código de vehículo, encontrar el nombre del empleado que lo
usa.
 Calcular el sueldo neto mensual de un empleado horas dado.
 Calcular el sueldo neto mensual de un empleado plazo indefinido dado.
 Calcular el sueldo neto mensual de un empleado dado.
 Dado un código un código de sindicato, encontrar los nombres de sus
afiliados.
 Para cada sindicato, indicar la cantidad de sus afiliados.
 Total de empleados
 Total de empleados horas.
 Total de empleados plazo indefinido.
 Total de vehículos.
 Total de vehículos asignados a empleados horas.
2.274
 Total de vehículos asignados a empleados plazo indefinido.
 Total de vehículos asignados a los empleados hora.
 Sueldo neto mensual mayor y menor de los empleados.
 Sueldo neto mensual mayor y menor de los empleados hora.
 Sueldo neto mensual mayor y menor de los empleados plazo indefinido.
 Total cancelado en remuneraciones brutas mensuales.

También podría gustarte