Vous êtes sur la page 1sur 74

Unidad I.

Lenguaje de
Programación Orientado a
Objetos.
Contenido
1. Implementación de Estructuras de Datos
2. Implementación de clases
3. Implementación de asociaciones y
dependencia
4. Implementación de Herencia y Polimorfismo
Estructuras de Datos
Estructuras de datos clásicas

 - Son variables que pueden contener muchos datos en lugar


de un solo dato. A cada dato se le llama elemento.

 - Ejemplo : un arreglo.

 - Están en memoria(los archivos y las tablas de Bd’s están en


disco).
Estructuras de Datos
Estructuras de datos clásicas

Hay tres tipos de estructuras de datos clásicas en java:


a. Los arreglos.

b. Colección: implementan la interfaz collection; entre ellas la


interfaz Set y la interfaz List.

c. Mapas: implementan la interfaz map.


Colecciones
Interfaz Collection

a. Interfaz que cumple las estructuras clásicas de datos de


estilo colección.

b. Algunas clases que la implementan:Vector, Hashtable,


LinkedList, ArrayList; entre otros.

c. Permite tratar todas estas clases de la misma forma.


Colecciones
Interfaz Collection
(estructura Jerárquica)
Colecciones
Métodos de Interfaz Collection

La variable ‘o’ es de tipo objeto:


a. add(o) : añade objeto a la colección.
b. remove(o): elimina objeto de la colección.
c. contains(o): devuelve true si el objeto esta en la colección.
d. isEmpty() : true si la colección esta vacía.
e. size(): retorna el número de elementos de la colección,
f. toArray(): retorna un array de objetos, con todos los
objetos de la colección,
Colecciones
Tips Collection

a. Todos los métodos sirven para poner elementos en la


colección.
b. Para consultar elementos de una colección se utiliza la
interfaz Iterator.
c. El método iterator() devuelve una interfaz para recorrer
los elementos de una colección.
Colecciones
Interfaz Iterator

a. Se encuentra en el paquete java.util


b. Recorre secuencialmente los elementos de una colección.
Sus métodos de instancia son:
- hasNext(): true si hay un elementos siguiente al actual.
- next(): devuelve el siguiente elemento. Lanza un
NoSuchElement Exception sino se encuentra este
elemento.
Colecciones
Interfaz iterator

El siguiente código imprime los elementos de una colección:

Iterator ite = colección.iterator();


while(ite.hastNext()){
System.out.println(ite.next());
}

Donde ‘colección’ es un objeto que implementa la interfaz


Collection(Ejem: podria ser un ArrayList entre otros).
Colecciones
Bucle for-each

Utilizar y recorrer colecciones con iterator puede parecer un


tanto complicado. Desde java 5 aparece el for-each.
a. Sirve para recorrer los elementos de :
- Colecciones.
- Arreglos.

b. Es útil cuando:
-Se quiere recorrer todos los elementos.
- No nos importa el valor del índice.
Colecciones
Sintaxis Bucle for-each
for (tipo variable: estructura){
//código
}

int suma = 0;
List<Integer> arreglo= new ArrayList<Integer>();
…..
for(int elemento:arreglo){
suma += elemento;
}
pro1.java
Colecciones
La interfaz Set

- Hereda de la interfaz Collection.

- Por ello tiene todos los métodos de Collection.

- Con el método add, si tratamos de adicionar dos elementos


iguales solo guardara uno.

- Se usa en colecciones sin valores repetidos.


Colecciones
La interfaz Set

- Pero sigue siendo una interfaz.

- Las interfaces no se pueden instanciar con new.

- ¿Cómo la instanciamos?
Colecciones
La interfaz Set
- El new se hace con las clases.
- Pero se guarda en una variable Set.
- Se manipula con los métodos de la interfaz Set
Set <Libreta> conjunto = new TreeSet<Libreta>
Donde Libreta es una clase(tipo de dato) con sus atributos y
métodos propios.

- Es decir TreeSet solo aparece en el new, en todo lo demás se


maneja con Set. TreeSet es una clase que implementa la interfaz
Set. <Libreta>, le decimos al compilador que el objeto conjunto
es un Set del tipo Libreta actuando como TreeSet.
Colecciones
La interfaz Set y Collection

- Son excelentes para recorridos secuenciales de los datos

- Para llegar de un elemento a otro hay que pasar por todos


los demás elementos.

- Pero a veces se necesita acceso directo, sin pasar por los


elementos anteriores.
Colecciones
La interfaz List

- Se accede a un elemento directamente.

- Añade un nuevo método get(p) donde p es la posición del


elemento que queremos encontrar.

- Como es collection devuelve un objeto.


Colecciones
La interfaz List

Métodos:
 isEmpty() : si la lista esta vacia.

 size(): número de elementos de la lista.

- La interfaz List pertenece a java.util

- isEmpty() y size() provienen de la interfaz Collection.


Colecciones
La interfaz List

- Como la lista es una estructura de datos del tipo Collection,


puede utilizar perfectamente el bucle for – each.

- List es una interfaz por lo que no podemos utilizar new.

- Podemos digitar: List empleados;

- La interfaces entonces nos devuelven un objeto que no


sabemos de que tipo es, pero si podemos utilizarlo(potencia de
las interfaces: Puede ser un objeto ArrayList o LinkedList)
Colecciones
La interfaz List

- A veces queremos crear objetos de la interfaz List.

- Se debe utilizar las clases que implementan la interfaz List:


a. ArrayList: la lista se guarda en un arreglo.
- Rápido para consultas.
- Tiempo aceptable para inserciones.
b. LinkedList: se implementa con punteros.
- Rápido en inserciones al final de la lista.
- Un tanto lento en consultas.
Colecciones
La interfaz List

- En la mayoría de casos es mejor ArrayList.

- El new se hace con las clases.

- List list = new ArrayList();


Colecciones
Caracteristicas de interface List

- ¿Qué especificamos?
a. El tipo de colección.
b. El tipo de objeto que contendrá.

- Incrementan su capacidad en demanda.

- Guarda los elementos en orden.


Colecciones
Caracteristicas de interface List

- Se basan en la gestión interna del almacenamiento y


recuperación de elementos.

- Prácticamente son contenedores de elementos.

- Son estructuras más complejas que los arrays ya que además


de tener interfaces para la agregación, extracción; adiciona
además la búsqueda, inserción y borrado.
Colecciones
Caracteristicas de interface List

- Los tipos de objetos que almacenan deben de estar


relacionados a los objetos envoltura.

- Tienen una serie de interfaces y clases para trabajar de forma


abstracta con ellas.

- Algunas colecciones aceptan duplicados y otras no.


Colecciones
Ejemplos implementación de List con clase
ArrayList
import java.util.*;
public class Programa {
public static void main(String arg[]) {
int temp = 0;
List<Integer> lp = new ArrayList<Integer>();
// El tipo es List y lo implementamos con ArrayList
// Utilizamos lista genérica…le decimos que contendrá objetos Integer
int sumaaltura = 0;
//llenamos la lista
for(int i=0;i<5;i++) {
lp.add(i); //el compilador convierte el int en Integer
}
Colecciones
Ejemplos implementación de List con clase
ArrayList
//Creamos objeto iterador para recorrer la lista
Iterator it = lp.iterator();
while(it.hasNext()) {
temp = (int) it.next(); //devuelve obj genérico, hay que pasarlo a int.
System.out.println(temp);
sumaaltura += temp;
} //fin while
System.out.println(sumaaltura);
} //fin main
} //fin clase
Colecciones
Ejemplos implementación de List con clase
ArrayList
En donde:
- El tipo es List y lo implementamos con ArrayList

- List es una subinterface de la interfaz Collecction y ArrayList


es la clase que implementa a List.

- El objeto lp es del tipo List actuando como un ArrayList.


Contenido
1. Implementación de Estructuras de Datos
2. Implementación de clases
3. Implementación de asociaciones y
dependencia
4. Implementación de Herencia y Polimorfismo
Implementación de Clases
• Las clases son tipos de dato definidos por el
usuario (por ejemplo Alumno, Empleado,
Materia, Auto, etc.).
• Los objetos son las variables de instancia de las
clases.
• Al escribir una aplicación en un lenguaje de
programación orientado a objetos, se escribe el
código para las clases; y además, se agrega el
código para la clase de la aplicación (que
contiene el método main).
29
Implementación de Clases

• Las clases se almacena en archivos con el nombre de la


clase, por ejemplo “Alumno.java” .
• Todas las aplicaciones en Java, inician su ejecución en el
método main, y finalizan en el mismo método.
• El método main, entonces, se encarga de instanciar
objetos de las clases definidas por el usuario; dichos
objetos inician la invocación de métodos de un objeto a
otro; y de esa forma, se ejecuta un programa orientado a
objetos.

30
Implementación de Clases
• La forma de escribir clases es procurando la flexibilidad y facilidad
de mantenimiento.
• Cuando un programador establece variables de instancia locales
(public), no se puede validar los valores asignados, por ejemplo:

//Archivo Caja.java //Archivo PruebaCaja.java


public class Caja { public class PruebaCaja {
public int tamaño; public static void main (String [] args){
public int peso; Caja c= new Caja();
…. c.tamaño = -5; // Legal pero mal!!!
} }
}
31
Implementación de Clases
• Para manejar este tipo de error, se debe escribir nuevamente
el código para ajustar la variable de instancia tamaño,
asignarle el modificador «private» y agregar el método
setTamaño(int tamaño); y hacer lo mismo con la variable
peso.
//Archivo Caja.java //Archivo PruebaCaja.java
public class Caja { public class PruebaCaja {
private int tamaño; public static void main (String []args)
private int peso; {
Caja c= new Caja();
public void setTamaño(int c.setTamaño(-5);
tamaño){ …..
this.tamaño=tamaño; }
} }
public void setPeso(int peso){
this.peso=peso;
}
} 32
Implementación de Clases
• Al hacer este cambio en la clase Caja, afecta los
programas de todos los que han reutilizado la clase, de
la forma c.tamaño=-5.
• La capacidad de hacer cambios en el código sin afectar
el de otras clases que lo utilizan es un beneficio clave de
la encapsulación.
• Para ocultar los detalles de implementación, se
establece una interfaz de programación pública (API).
• La interfaz pública son los métodos de acceso, su código
esta disponible para ser llamado desde otros códigos.

33
Implementación de Clases: encapsulación
• Al ocultar los detalles de implementación, se puede
escribir nuevamente el código del método (incluso de
las variables que se utilizan en la clase), sin forzar un
cambio en el código que llama al método modificado.
• Para que el código tenga mantenibilidad, flexibilidad y
extensibilidad, el diseño debe incluir la encapsulación.
• Como incluir encapsulación:
– Mantenga las variables protegidas (Con un modificador de
acceso, con frecuencia se usa private o protected).
– Crear métodos de acceso public, utilizar estos métodos para
acceder directamente a las variables.
– Para los Métodos, utilizar la convención de nomenclatura de
nombres de JavaBeans set <Propiedad> y get <Propiedad>
34
Implementación de Clases: encapsulación
• Los métodos de acceso getters y setters, acceden a las variables de
instancia de las clases.
• El código anterior no parece útil, ya que no realiza ningún tipo de
validación o transformación.
• No se observa el beneficio de usar getter y setter que no agregan
funcionalidad adicional.
• Sin embargo, eso es al inicio, ya que se puede cambiar de forma de
pensar después; y entonces, al agregar más código al método, no
se corrompe su API.
• Un buen diseño orientado a objetos es el que se planea para el
futuro.
• En el ejemplo siguiente, la lógica del método setIzquierda a
perdido la encapsulación.

35
Implementación de Clases: encapsulación
Class Ejemplo {
public int izquierda = 9;
public int derecha = 3;

public void setIzquierda (int izquierdaNum) {


izquierda = izquierdaNum;
derecha = izquierdaNum/3;
}
// aquí mucho más código complejo
}

• Al usar el método setIzquierda(), el valor de la variable derecha


siempre será la tercera parte del valor de la variable izquierda.
• Los usuarios de la clase Ejemplo, que no compartan la idea de la
tercera parte, no utilizaran el método setIzquierda(), y optaran por
ir directamente a cambiar el valor de las variables de instancia.
36
Implementar Clases y Asociaciones
• El diagrama de clases siguiente muestra:
• La clase de la aplicación: Prueba
• Clases definidas por el usuario: Taxi y Chofer
• La clase Prueba depende de Taxi y Chofer
• La clase Taxi se asocia con la clase Chofer
• Taxi y Chofer no muestran el método constructor, ni los métodos
setters y getters; sin embargo, un programador debe incluir el
código para dichos métodos.

37
Implementar Clases y Asociaciones
• En un diagrama de clases se inicia programando la clase
menos dependiente, en el diagrama anterior el orden de
programación es el siguiente:
– Chofer (no depende de ninguna clase)
– Taxi (depende de la clase Chofer, por la asociación)
– Prueba (depende las dos clases anteriores)
• La clase Chofer presenta la implementación de la
sobrecarga de métodos (un tipo de polimorfismo), ya
que incluye dos constructores:
– “public Chofer()”, sin argumento, y
– “public Chofer(String nombre)”, con argumento
• Así, un objeto Chofer puede instanciarse sin inicializar su
nombre, o inicializandolo. 38
Implementar Clases y Asociaciones
public class Chofer{ public String getNombre(){
private String nombre; return nombre;
public Chofer(){ }
//constructor sin argumentos public String toString(){
} return “\nNombre del Chofer: “
public Chofer(String nombre){ + nombre;
this.nombre=nombre; }
} }
public void setNombre(String nombre){
this.nombre=nombre;
}

39
Implementar Clases y Asociaciones
• El método toString() convierte un objeto Chofer a su representación en una
cadena String, y es un método heredado de la clase Object.

• En java, por omisión, todas las clases heredan de la clase Object.

• Los métodos de la clase Object son:


– String toString()
– Object clone()
– boolean equals(Object), etc.

• En la clase Chofer, el método toString(), ha sido sobreescrito (sobreescritura de


métodos, otro tipo de polimorfismo).

• this es la autoreferencia del objeto, y se usa para seleccionar explícitamente una


variable de instancia o un método, para dar más claridad o evitar colisión de
identificadores.
40
Implementar Clases y Asociaciones
public class Taxi{ public String getMatricula(){
private String matricula; return matricula;
}
private Chofer chofer;
public void setChofer(Chofer chofer){
public Taxi(){
this.chofer=chofer;
//constructor sin argumentos
}
}
public Chofer getChofer(){
public Taxi(String matricula,
return chofer;
Chofer chofer){
}
this.matricula=matricula;
public String toString(){
this.chofer=chofer;
return “Taxi con matricula: “ +
}
matricula+” y “ +
public void setMatricula(String
chofer.toString();
matricula){
}
this.matricula=matricula;
}
}
41
Implementar Clases y Asociaciones
• La clase Taxi también presenta el constructor sobrecargado:
– “public Taxi()”, sin argumentos, y
– “public Taxi(String matricula, Chofer chofer)”, con argumentos

• Así, un objeto Taxi puede instanciarse SIN INICIALIZAR sus


variables de instancia: matricula y chofer, si se usa el constructor
sin argumentos.

• Dado que la asociación significa: “Un objeto Taxi puede estar


asociado con un objeto de tipo Chofer o ninguno” (0..1), entonces
es posible crear un objeto Taxi que no posea un objeto Chofer.

• La clase Taxi también incluye los respectivos set y get para el


atributo de tipo Chofer.
42
Implementar Clases y Asociaciones
public class Prueba{
• Prueba es la clase
public static void main(String args[ ]){
de la aplicación
que implementa Chofer chofer=new Chofer(“Juan”);
el método main. Taxi taxi=new Taxi(“P-100100”, chofer);
System.out.println(taxi);
• El método System.out.println(taxi.toString());
println(String) de
String taxiychofer= taxi.toString();
la clase System,
imprime en System.out.println(taxiychofer);
consola el }
argumento. }

• El argumento debe ser un String, y si recibe un valor diferente de String, el


mismo método println convierte el argumento a String, invocando el método
toString heredado de la clase Object.

• El método main muestra tres formas validas de imprimir el objeto de tipo Taxi,
aplicando el método toString(). 43
Implementar Dependencia
• La dependencia es una relación de uso entre dos clases, una clase
usa a la otra.

De este diagrama se puede decir:


• La clase Prueba usa las clases Taxi y Chofer.
• En la practica, este tipo de relación se interpreta como que la clase
Prueba hace uso de la clase Taxi, ya sea instanciándola localmente
en un método (como sucede en este ejemplo), o bien,
recibiéndola como parámetro de entrada en uno de sus métodos. 44
Asociación de multiplicidad 1
• Si la asociación del
ejemplo anterior,
cambiará la multiplicidad
de 0..1 a 1 (como se
muestra en el diagrama),
este caso implicaría que
cada objeto de la clase
Taxi deberá tener
asociado un objeto de
tipo Chofer, durante la
ejecución del programa.
• En este caso, el constructor sin argumentos NO debería ser usado.
• IMPORTANTE: En ocasiones, es posible que las restricciones de la
multiplicidad en una asociación, se validen solo hasta el momento
de almacenar su datos en un archivo o una base de datos. 45
Asociación de multiplicidad 1
public class Taxi{ public void setChofer(Chofer chofer){
private String matricula; this.chofer=chofer;
private Chofer chofer; }
// public Taxi(){ public Chofer getChofer(){
//constructor sin argumentos return chofer;
// } }
public Taxi(String matricula, Chofer chofer){ public String toString(){
this.matricula=matricula; return “Taxi con matricula: “ +
this.chofer=chofer; matricula+” y el chofer: “
} + chofer.toString();
public void setMatricula(String matricula){ }
this.matricula=matricula; }
}
public String getMatricula(){
return matricula;
} 46
Asociación de multiplicidad 0..*
• Si la asociación del diagrama anterior, cambiará la multiplicidad a
0..* (como se muestra en este diagrama), esta situación obligaría a
que cada objeto de la clase Taxi podrá tener asociado ninguno,
uno o varios objetos de tipo Chofer.
• En este caso, la variable de instancia de tipo Chofer (en la clase
Taxi), deberá ser una estructura de datos, que podrá tener
almacenado cualquier cantidad de objetos de tipo Chofer.

47
Asociación de multiplicidad 0..*
• La clase Chofer mantiene la misma codificación de los ejemplos
anteriores, pero la clase Taxi quedaría así:
import java.util.ArrayList;
public class Taxi{
private String matricula;
private ArrayList<Chofer> choferes= new ArrayList<Chofer>();
public Taxi(){
//constructor sin argumentos
}
public Taxi(String matricula){
this.matricula=matricula;
}
public void agregarChofer(Chofer chofer){
choferes.add(chofer);
} 48
Asociación de multiplicidad 0..*
public Chofer getChofer(int indice){ //clase Taxi
if (this.getCantidad()>indice)
{
Chofer chofer=choferes.get(indice);
return new Chofer(chofer.getNombre());
} else // posicion invalida
throw new IllegalArgumentException ( "Error: Posicion invalida");
}
public int buscarChofer(Chofer chofer){
return choferes.indexOf(chofer); //devuelve -1 si no esta en la lista
}
public void setChofer(int indice, Chofer chofer){
if (this.getCantidad()>indice)
choferes.set(indice, chofer);
else // posicion invalida
throw new IllegalArgumentException ( "Error: Posicion invalida");
49
}
Asociación de multiplicidad 0..*
public void eliminarChofer(Chofer chofer){ //Clase Taxi
if (choferes.contains(chofer))
choferes.remove(chofer);
else // objeto no existe en la lista
throw new IllegalArgumentException ( "Error: Chofer no existe");
}
public int getCantidad(){
return choferes.size();
}
public void setMatricula(String matricula){
this.matricula=matricula;
}
public String getMatricula(){
return matricula;
}
50
Asociación de multiplicidad 0..*
public String toString(){ //Clase Taxi
String nombres=new String();
for (Chofer chofer:choferes)
nombres=nombres+chofer.toString();
return "Taxi con matricula: " + matricula+" ; " + nombres;
}
}

• En la clase Taxi se incluye los métodos:


– void agregarChofer(Chofer)
– Chofer getChofer(int)
– int buscarChofer(Chofer)
– void setChofer(int, Chofer)
– void eliminarChofer(Chofer)
– int getCantidad() 51
Asociación de multiplicidad 0..*
• En la clase Taxi los métodos getChofer y setChofer, validan que
exista el número de la posición del objeto a obtener o modificar,
sino es válida se lanzaría una Exception.
• De igual manera, el método eliminarChofer valida que el objeto a
eliminar exista.
• La clase de la aplicación que prueba todos los métodos es:

public class Prueba {

public static void main(String args[ ]){


Chofer chofer1=new Chofer("Juan");
Chofer chofer2=new Chofer("Pedro");
Chofer chofer3=new Chofer("José");
Chofer chofer4=new Chofer("Mario");
Taxi taxi=new Taxi("P-100100");
52
Asociación de multiplicidad 0..*
taxi.agregarChofer(chofer1); //Clase Prueba
taxi.agregarChofer(chofer2);
taxi.agregarChofer(chofer3);
System.out.println(taxi+ "\ntiene "+taxi.getCantidad()+ " choferes");
int pos=taxi.buscarChofer(chofer4);
System.out.println("\n"+chofer4+" se encuentra en la posicion "+pos);
pos=taxi.buscarChofer(chofer2);
System.out.println("\n"+chofer2+" se encuentra en la posicion "+pos);
taxi.setChofer(pos, chofer4);
System.out.println("\n"+chofer2+" fue cambiado por "+chofer4);
System.out.println(taxi);
taxi.eliminarChofer(chofer1);
System.out.println("\n"+chofer1+" fue eliminado!!!");
System.out.println(taxi);
} //fin del main
} // fin de la clase Prueba 53
Asociación de multiplicidad 1..*
• Si la asociación del diagrama de clases anterior, cambiará a
multiplicidad de 1..* (como se muestra en este diagrama), esta
situación obligaría a que cada objeto de la clase Taxi deberá tener
asociado uno o varios objetos de tipo Chofer.
• En este caso, la variable de instancia de tipo Chofer (en la clase
Taxi), deberá ser una estructura de datos que podrá almacenará al
menos 1 objeto de tipo Chofer, y al crearse el objeto Taxi, debe
agregarse, por lo menos un objeto de tipo Chofer.

54
Asociación de multiplicidad 1..*
• El código de la clase import java.util.ArrayList;
Taxi del ejemplo public class Taxi{
anterior (multiplicidad private String matricula;
0..*) permite crear private ArrayList<Chofer>
objetos de tipo Taxi aún choferes= new ArrayList<Chofer>();
sin agregarle ningún //public Taxi(){
objeto de tipo Chofer. // constructor sin argumentos
//}
• Para aplicar la //public Taxi(String matricula){
multiplicidad de 1..* // this.matricula=matricula;
será necesario evitar //}
que se creen objetos de public Taxi(String matricula, Chofer chofer){
tipo Taxi sin al menos this.matricula=matricula;
un objeto de tipo agregarChofer(chofer);
Chofer. }
55
Implementar Clases de Asociación
• Si a un Taxi se le asigna un Chofer en una fecha específica, la fecha
se considera un atributo de la asociación, y será necesario crear
una Clase asociación con el nombre Asignación.

• En este diagrama de
clases, cada objeto de
la clase Taxi podrá
tener asociado uno,
varios o ningún objeto
(0..*) de tipo
Asignación, y cada
objeto de tipo
Asignación deberá
tener asociado un
objeto de tipo Chofer.
56
Implementar Clases de Asociación
• El orden de programación de las clases es el siguiente:
− Chofer
− Asignacion
− Taxi
− Prueba
• Chofer no depende de ninguna clase, Asignación depende de
Chofer, Taxi depende de Asignación, y Prueba depende de Taxi y
Chofer.
• La clase Asignacion, deberá tener una variable de tipo Chofer, para
almacenar un objeto.
• La clase Taxi, tendrá una variable de instancia de tipo Asignacion,
que deberá ser una estructura de datos para almacenar los objetos
(0..*) de tipo Asignación.
• Además, la clase Taxi deberá incorporar métodos necesarios para
manipular la lista de asignaciones.
57
Implementar Clases de Asociación
public class Asignacion{ public String getFecha(){
private String fecha; return fecha;
private Chofer chofer; }
public Asignacion(){ public void setChofer(Chofer){
//constructor sin argumentos this.chofer = chofer;
} }
public Asignacion(String fecha, public Chofer getChofer(){
Chofer chofer){ return chofer;
this. fecha = fecha; }
this.setChofer( chofer); public String toString(){
} return “Fecha de asignación: “ +
public void setFecha(String fecha){ fecha + ” ; chofer: ” +
this. fecha = fecha; chofer.getNombre();
} }
}
58
Implementar Clases de Asociación
import java.util.ArrayList;
public class Taxi{
private String matricula;
private ArrayList<Asignacion> lista= new ArrayList<Asignacion>();
public Taxi(){
//constructor sin argumentos
}
public Taxi(String matricula, String fecha, Chofer chofer){
this.matricula=matricula;
Asignacion a=new Asignacion(fecha,chofer);
agregarAsignacion(a);
}
public void agregarAsignacion(Asignacion a){
lista.add(a);
}
59
Implementar Clases de Asociación
public int getCantidad(){ //Clase Taxi
return lista.size();
}
public Asignacion getAsignacion(int indice){
Asignacion a=lista.get(indice);
return new Asignacion(a.getFecha(), a.getChofer());
}
//incluir aca public void setMatricula(String)
//incluir aca public String getMatricula()
public String toString(){
String nombres=new String();
for (Asignacion a:lista)
nombres=nombres+a.toString();
return “Taxi con matricula: “ + matricula+” ; “ + nombres;
}
60
Implementar Clases de Asociación
public class Prueba{
public static void main(String args[ ]){
Chofer chofer=new Chofer(“Juan”);
Taxi taxi=new Taxi(“P-100100”, “11/08/2014”, chofer);
System.out.println(taxi);
}
}

• La clase Prueba solo usa las clases Taxi y Chofer, no usa la clase
Asignacion.

• La clase Taxi recibe los datos para crear el objeto de Asignacion, y


luego agregarlo a las lista de asignaciones (ArrayList), de esa
manera ambos objetos (Taxi y Asignacion) quedan asociados.
61
Implementar Asociación Reflexiva
• Si la clase origen de la asociación es la misma clase fin, entonces
existe una asociación reflexiva como muestra el siguiente diagrama
de clases.
• Esta asociación implica que un objeto de tipo Chofer definirá
dentro de sus variables de instancia otro objeto de tipo Chofer (o
ninguno como muestra la multiplicidad 0..1).
• La asociación reflexiva presenta los nombres de los roles, al
codificar la asociación el nombre de rol se utiliza como el nombre
de variable de instancia.

62
Implementar Asociación Reflexiva
public class Chofer{ public void setSuplente(Chofer
private String nombre; suplente){
private Chofer suplente; this.suplente=suplente;
public Chofer(){ }
} //constructor sin argumentos
public Chofer(String nombre public Chofer getSuplente(){
Chofer suplente){ return suplente;
this.nombre=nombre; }
setSuplente(suplente);
public String toString(){
} return “Nombre del Chofer: “
public void setNombre(String nombre){ + nombre +
this.nombre=nombre; ” ; nombre del suplente: “
} + suplente.getNombre();
public String getNombre(){ }
return nombre; }
}
63
Implementar Agregación
• La agregación es un tipo especial de asociación donde se agrega el
matiz semántico de que la clase de donde parte la relación
representa el “todo” y las clases relacionadas “partes”.
• Realmente, Java y la mayoría de lenguajes orientados a objetos no
disponen de una implementación especial para este tipo de
relaciones. Básicamente se tratan como las asociaciones
ordinarias.
• En algunas ocasiones, la clase que representa el todo, será la
responsable de crear los objetos de las «partes», pero no es
obligatorio.

64
Implementar Agregación
public class Materia{ import java.util.ArrayList;
private String codigo; public class Carrera{
public Materia(){ private String nombre;
//constructor sin argumentos private ArrayList<Materia> materias;
} materias=new ArrayList<Materia>();
public Materia(String codigo){
this.codigo=codigo; public Carrera(){
} //constructor sin argumentos
public void setCodigo(String }
codigo){
this.codigo=codigo; public Carrera(String nombre){
} this.nombre=nombre;
public String getCodigo(){ }
return codigo;
} public void setNombre(String nombre){
public String toString(){ this. nombre=nombre;
return “Codigo: “ + codigo }
}
} 65
Implementar Agregación
//Clase Carrera
public String getNombre (){ public int getCantidad(){
return nombre; return materias.size();
} }
public void agregarMateria(
Materia materia){ public String toString(){
materias.add(materia); String codigos=new String();
}
for each(Materia mat:materias)
codigos=codigos+mat.toString();
public Materia getMateria(
int indice){ return “Nombre de la carrera: “ +
Materia mat; nombre + ” ; Materias: “ +
mat=materias.get(indice); codigos;
}
return new }
Materia(mat.getNombre());
} 66
Implementar Agregación
• La clase Prueba crea dos
objetos de tipo Carrera y
public class Prueba{
dos de tipo Materia.
public static void main(String args[ ]){
Materia mat1=new Materia(«PRN215»);
• Al objeto Carrera de
Materia mat2=new Materia(«PRN315»);
Sistemas se le agregan los
Carrera car1=new Carrera(«Sistemas»);
dos objetos de tipo
Carrera car2=new Carrera(«Industrial»);
Materia, y al objeto
car1.agregarMateria(mat1);
Carrera de Industrial, se
car1.agregarMateria(mat2);
le agrega un objeto de
car2.agregarMateria(mat1);
tipo Materia.
System.out.println(car1);
System.out.println(car2);
• De esa manera, las dos
}
carreras comparten un
}
objeto agregado, la
Materia PRN215. 67
Implementar Composición
• La composición es un tipo de agregación que agrega el matiz de
que la clase “todo” controla la existencia de las clases “parte”.
• Es decir, normalmente la clase “todo” creará al principio las clases
“parte” y al final se encargará de su destrucción.
• Dado el ejemplo siguiente, la clase Cuenta se compone de un
registro de Movimientos, de tal forma que queda constancia tras
cada abono o retiro realizado en la Cuenta.

68
Implementar Composición
public class Cliente{ public class Movimiento{
private String nombre; private String tipo;
public Cliente(){ private double monto;
//constructor sin argumentos public Movimiento(String tipo,
} double monto){
public Cliente(String nombre){ this.tipo=tipo;
this.nombre=nombre; this.monto=monto;
} }
public void setNombre(String public void setTipo(String tipo){
nombre){ this.tipo=tipo;
this.nombre=nombre; }
} public String getTipo(){
public String getNombre(){ return tipo;
return nombre; } //incluir setMonto, getMonto()
} public String toString(){
public String toString(){ return «Tipo: » + tipo + «; Monto: »
return “Nombre: “ + nombre + monto;
} }
} } 69
Implementar Composición
public class Cuenta{ public void abonar(double cant){
private double saldo; Movimiento mov=new Movimiento(
«abono», cant);
private ArrayList<Cliente> propietarios;
listM.add(mov);
propietarios=new ArrayList<Cliente>(); saldo = saldo + cant;
private ArrayList<Movimiento> listaM; }
listaM = new ArrayList<Movimiento>();
public Cuenta(String propietario, public void retirar(double cant){
Movimiento mov=new Movimiento(
double saldo){
«retiro», cant);
Cliente pro=new Cliente(propietario); listM.add(mov);
agregarPropietario(pro); saldo = saldo - cant;
this.nombre = nombre; }
}
public String toString(){
//setSaldo(double saldo)
//Capturar en una variable String
//getSaldo() //saldo, propietarios y
public void agregarPropietario(Cliente //movimientos
prop){ }
propietarios.add(prop); }
} 70
Implementar Composición
import java.util.ArrayList;
public class Cuenta{
private double saldo;
private ArrayList<Cliente> propietarios=new ArrayList<Cliente>();
private ArrayList<Movimiento> listaM = new ArrayList<Movimiento>();
public Cuenta(String propietario, double saldo){
Cliente pro=new Cliente(propietario);
agregarPropietario(pro);
this.nombre = nombre;
}
//incluir setSaldo y getSaldo()

public void agregarPropietario(Cliente prop){


propietarios.add(prop);
}
71
Implementar Composición
// Clase Cuenta
public void abonar(double cant){
//validar que cant sea positivo, sino lanzar Exception
Movimiento mov=new Movimiento( “abono”, cant);
listM.add(mov);
saldo = saldo + cant;
}
public void retirar(double cant){
//validar que cant sea positivo o menor o igual que saldo
Movimiento mov=new Movimiento(“retiro”, cant);
listM.add(mov);
saldo = saldo - cant;
}
public String toString(){
//Capturar en una variable String
//saldo, propietarios y
//movimientos
}
} 72
Implementar Composición
public class Prueba{
public static void main(String args[ ]){
Cuenta cuenta=new Cuenta(«Juan», 100);
cuenta.abonar(100);
cuenta.abonar(50);
agregarPropietario(«Maria»);
cuenta.retirar(150);
System.out.println(cuenta);
}
}

• La clase Prueba solo crea un objeto de tipo cuenta.

• La clase Cuenta recibe en el constructor los parámetros necesarios


para crear un objeto de tipo Cliente que será el propietario de la
Cuenta. 73
Implementar Composición
• En los métodos abonar() y retirar() de la clase Cuenta se crea cada
objeto de tipo Movimiento, que son las partes de las que se forma
la Cuenta.
• En general, las composiciones tienen una implementación similar a
las asociaciones, con la diferencia de que el objeto principal
(Cuenta) realizará en algún momento la construcción y/o
destrucción de los objetos compuestos (Movimientos).

• Al igual que en el ejemplo de la clase Taxi, será necesario incluir en


la clase Cuenta métodos para manipular las listas, por ejemplo:
buscarPropietario(), setPropietario(), eliminarPropietario(), etc.

• Además, es necesario incluir las validaciones necesarias, tal como


se estudiaron con el ejemplo de la lista de Chofer que manipula la
clase Taxi en el ejemplo de las asociaciones con multiplicidad 0..*
74

Vous aimerez peut-être aussi