Está en la página 1de 27

Interfaces

(en JDK 7 y versiones anteriores)

• Interfaces
- ¿Qué son las interfaces?
- ¿Para que sirven?
• Declaración de interfaces en java
• Un ejemplo:
- Declarando interfaces
- Implementando múltiples interfaces
- Upcasting
• Colisiones en interfaces
• Las interfaces Comparable y Comparator
• Interfaces vs. clases abstractas
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
Interfaces
¿Qué son?, ¿Para qué sirven?
¿Puede Pájaro ser subclase de Animal, Mascota y
Voladores? NO
Object

extends
Animal getNombre() despegar()
Mascota aterrizar()
comer() setNombre()
Voladores
extends
Una clase puede implementar más de una
Pájaro interface y de esta manera provee un
mecanismo “similar” a la herencia múltiple.

• Una interface java es una colección de definiciones de métodos sin


implementación/cuerpo y de declaraciones de variables de clase constantes, agrupadas
bajo un nombre.
• Las interfaces proporcionan un mecanismo para que una clase defina comportamiento
(métodos) de un tipo de datos diferente al de sus superclases.
• Una interface establece qué debe hacer la clase que la implementa, sin especificar el
cómo.
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
Declaración de Interfaces

¿Cómo se define una interface?


package nomPaquete;
public interface UnaInter extends SuperInter1, SuperInter2, ... {
Declaración de métodos: implícitamente public y abstract
Declaración de constantes: implícitamente public, static y final

• El especificador de acceso public, establece que la interface puede ser usada por
cualquier clase o interface de cualquier paquete. Si se omite el especificador de acceso, la
interface solamente podría ser usada por las clases e interfaces contenidas enel mismo
paquete que la interface declarada.

• Una interface puede extender múltiples interfaces. Hay herencia múltiple de interfaces.
• Una interface hereda todas las constantes y métodos de sus SuperInterfaces.

AyED - Cursada 2021 Laura Fava - Pablo Iuliano


Declaración de Interfaces
• Ambas declaraciones son equivalentes. Las variables son implícitamente
public, static y final (constantes). Los métodos de una interface son
implícitamente public y abstract.
public interface Volador { public interface Volador {
public static final long UN_SEGUNDO=1000; long UN_SEGUNDO=1000;
public static final long UN_MINUTO=60000; long UN_MINUTO=60000;
public abstract String despegar(); String despegar();
public abstract String aterrizar(); String aterrizar();
public abstract String volar(); String volar();
} }

• Esta interface Volador establece qué debe hacer la clase que la implementa, sin
especificar el cómo.
• Las clases que implementen Volador deberán implementar los métodos despegar(),
aterrizar() y volar(), todos públicos y podrán usar las constantes UN_SEGUNDO y
UN_MINUTO. Si una clase no implementa algunos de estos métodos, entonces la clase
debe declararse abstract.
• Las interfaces se guardan en archivos con el mismo nombre de la interface y con extensión
.java.

AyED - Cursada 2021 Laura Fava - Pablo Iuliano


Implementación de Interfaces
Para especificar que una clase implementa una interface se usa la palabra clave
implements
public interface Volador {
public class Pajaro long UN_SEGUNDO=1000;
long UN_MINUTO=60000;
implements Volador {
public String despegar();
. . . public String aterrizar();
} public String volar();
}

• Una clase que implementa una interface, hereda las constantes y debe implementar cada
uno de los métodos declarados en la interface!!!.
• Una clase puede implementar más de una interface y de esta manera provee un mecanismo
similar a la herencia múltiple.

public class Pajaro extends Animal implements Volador, Mascota {


public String despegar() {..}
public String aterrizar(){..} public interface Macota{
public String volar(){..} public getName();
public getName(){..} public setName();
public setName(){..} }
}

AyED - Cursada 2021 Laura Fava - Pablo Iuliano


Implementación de Interfaces
Considere el ejemplo de una interface que describe cosas que vuelan. El vuelo incluye
acciones tales como despegar, aterrizar y volar.

Animal

+comer()

Araña Gato

+Araña() +Gato()
+ comer() +Gato(String n)
+jugar()

Cada objeto despega, aterriza y vuela de manera diferente,


por lo tanto necesita implementar un procedimiento
diferente para acciones similares Además de implementar la interface
Volador, Pajaro es parte de una
jerarquía de clases.
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
Implementación de Interfaces
• Cuando una clase implementa una interface se establece como un contrato entre la
interface y la clase que la implementa.
• El compilador hace cumplir este contrato asegurándose de que todos los métodos
declarados en la interface se implementen en la clase.

public class Pajaro extends Animal public class Avion extends Transporte
implements Mascota, Volador { implements Volador{
String nombre; int velocidadMax;
public Pajaro(String s) { . . .
nombre = s; // Métodos de la Interface Volador
} public String despegar(){
// Métodos de la Interface Mascota return(“encender motores");
public void setNombre(String nom){ }
nombre = nom;}
public String aterrizar(){
public String getNombre(){
return "El Pájaro se llama "+nombre;} return(“Exponer ruedas");
}
// Métodos de la Interface Volador public String volar(){
public String despegar(){ return(“Guardar ruedas");
return(“Agitar alas"); }
} }
public String aterrizar(){
public interface Volador {
return(“Bajar alas");
long UN_SEGUNDO=1000;
}
long UN_MINUTO=60000;
public String volar(){
public String despegar();
return(“Mover alas");
public String aterrizar();
}
public String volar();
}
AyED - Cursada 2021 } Laura Fava - Pablo Iuliano
Interfaces y herencia múltiple
• El mecanismo que permite crear una clase derivada de varias clases bases, se llama
herencia múltiple. Como cada clase tiene una implementación propia, la combinación puede
generar ambigüedades.

• Java, NO soporta herencia múltiple pero provee interfaces para lograr un comportamiento
“similar”. Como las interfaces no tienen implementación, NO causa problemas combinarlas,
entonces: una clase puede heredar de una única clase base e implemenatar tantas
interfaces como quiera.
Tipos de Datos
Clase base (concreta Interface 1
o abstracta)
Interface 2
Herencia
upcasting
Interface n
upcasting
upcasting
Clase Derivada Interface 1 Interface 2 .... Interface n
Cada una de las interfaces que la clase implementa, provee de un tipo de dato
al que puede hacerse upcasting.
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
Interfaces y upcasting
package taller;
public class PruebaInterfaces {
• Las interfaces definen un nuevo tipo de
public static void partida(Volador v){ dato entonces, podemos definir:
v.despegar(); Volador[] m = new Volador[]
}
El binding dinámico • El mecanismo de upcasting no tiene
resuelve a que método en cuenta si Volador es una clase
invocar.
concreta, abstracta o una interface.
public static void main(String[] args) {
Funciona de la misma manera.
Volador[] m = new Volador[3];
m[0]= new Avion(); • Polimorfismo: el método despegar()
Upcasting castea al es polimórfico, se comportará de
m[1]= new Helicóptero();
tipo de la interface acuerdo al tipo del objeto receptor, esto
m[2]= new Pajaro();
for (int j=0; j<m.length; j++) es, el despegar() de Avion es diferente
partida(m[j]); al despegar() de Pajaro.
}}

El principal objetivo de las interfaces es permitir el “upcasting” a otros tipos, además del upcasting al tipo base.
Un mecanismo similar al que provee la herencia múltiple.

AyED - Cursada 2021 Laura Fava - Pablo Iuliano


Interfaces vs. Clases Abstractas
• Las interfaces y las clases abstractas proveen una interface común. La interface Volador,
podría definirse como una clase abstracta, y las clases concretas que la extiendan
proveerán el comportamiento correspondiente.
• Las interfaces son completamente abstractas, no tienen ninguna implementación.
• Con interfaces no hay herencia de métodos, con clases abstractas si.
• No es posible crear instancias de clases abstractas ni de interfaces.
• Una clase puede extender sólo una clase abstracta, pero puede implementar múltiples
interfaces.

¿Uso interfaces o clases abstractas?


• Si es posible crear una clase base con métodos sin implementación y sin variables de
instancia, es preferible usar interfaces.
• Si estamos forzados a tener implementación o definir atributos, entonces usamos clases
abstractas.
• Java no soporta herencia múltiple de clases, por lo tanto si se quiere que una clase
sea además del tipo de su superclase de otro tipo diferente, entonces es necesario usar
interfaces.
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
Ordenando objetos
¿Qué pasa si definimos un arreglo con elementos de tipo String y los ordenamos?
public class Test {
public static void main(String[] args) {
String animales[] = new String[4];
animales[0] = "camello"; Arrays es una clase del paquete java.util, la
cual sirve para manipular arreglos, provee
animales[1] = "tigre"; mecanismos de búsqueda y ordenación.
animales[2] = "mono";
animales[3] = "pájaro"; animal o: camello
for (int i = 0; i < 4; i++) { animal 1: tigre
System.out.println("animal "+i+":"+animales[i]); animal 2: mono
} animal 3: pájaro
Arrays.sort(animales);
for (int i = 0; i < 4; i++) { animal o: camello
System.out.println("animal "+i+":"+animales[i]); animal 1: mono
} animal 2: pájaro
} animal 3: tigre
}

Después de invocar al método sort(), el arreglo quedó ordenado alfabéticamente. Esto es


porque los objetos de tipo String son comparables.
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
Ordenando objectos
¿Qué pasa si ordenamos objetos de tipo Persona?
public class Test {
public static void main(String[] args){
public class Persona {
Persona personas[] = new Persona[4];
private String nombre;
personas[0]= new Persona(“Paula",“Gomez",16);
private String apellido;
personas[1]= new Persona(“Ana",“Rios",6);
private int edad;
personas[2]= new
public Persona
Persona(“Maria",“Ferrer",55);
personas[3]= new Persona(“Juana",“Araoz",54); (String n,String a,int e){
nombre=n;
apellido=a;
for (int i=0; i<4;i++){ edad=e;
System.out.println(i+”:”personas[i]); }
} public String toString(){
Arrays.sort(personas); return apellido+", "+nombre;
for (int i = 0; i<4; i++) { }
. . .
System.out.println(i+":"+personas[i]);
}
}
}
¿cómo ordenamos?, ¿por nombre, por apellido, por edad??. Al invocar al método sort(), y pasar el
arreglo personas, da un error porque los objetos Persona no son comparables.
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
La interface java.lang.Comparable
Hemos visto que cuando creamos una clase, comúnmente se sobrescribe el método
equals(Object o), para determinar si dos instancias son iguales o no. También es común,
necesitar saber si una instancia es mayor o menor que otra (con respecto a alguno de sus
datos) 🡺 así, poder compararlos
La interface Comparable<T>
Si una clase implementa la interface java.lang.Comparable, hace a sus instancias
comparables. Esta interface tiene sólo un método, compareTo(), el cual determina cómo
comparar dos instancias de una misma clase. El método es el siguiente:
La intención es que cada clase que la
public interface Comparable<T> { implemente reciba un T del tipo de la clase
public int compareTo(T o);
}
Este método retorna:
=0: si el objeto receptor es igual al pasado en el argumento.
>0: si el objeto receptor es mayor que el pasado como parámetro.
<0: si el objeto receptor es menor que el pasado como parámetro.

AyED - Cursada 2021 Laura Fava - Pablo Iuliano


La interface java.lang.Comparable
La clase Persona implementa la interface Comparable<T>
import java.util.*;
public class Test {
public class Persona
public static void main(String[] args){
implements Comparable<Persona> {
Persona personas[] = new Persona[3]; private String nombre;
personas[0]= new Persona(“Paula",“Gomez",16); private String apellido;
personas[1]= new Persona(“Ana",“Rios",6); private int edad;
personas[2]= new Persona(“Maria",“Ferrer",55); public Persona(String n,String a,
int e){
personas[3]= new Persona(“Juana",“Araoz",54);
nombre=n;
for (int i=0; i<4;i++){
apellido=a;
System.out.println(i+”:”+personas[i]); edad=e;
} }
Arrays.sort(personas); public String toString(){
return apellido+", "+nombre;
for (int i = 0; i<4; i++) { }
System.out.println(i+":"+personas[i]); public int compareTo(Persona o){
} return this.edad - o.edad;
}
} Al invocar al método sort(), ahora si los puede ordena,
}
con el criterio establecido en el compareTo()
0:Gomez, Paula:16 0:Rios, Ana:6
1:Rios, Ana:6 1:Gomez, Paula:16
2:Ferrer, Maria:55 2:Araoz, Juana:54
3:Araoz, Juana:54 3:Ferrer, Maria:55
AyED - Cursada 2021 Laura Fava - Pablo Iuliano
La interface java.lang.Comparable
La clase Persona implementa la interface Comparable<Persona>
import java.util.*;
public class Persona implements Comparable<Persona> {
private String nombre;
private String apellido; public class Test {
private int edad; public static void main(String[] args){
public Persona(String n, Stringpublic
a, int e){
static void main(String[] args) {
nombre=n;
Persona per1 = new Persona("Paula","Gomez",16);
apellido=a;
edad=e; Persona per2 = new Persona("María","Shan",10);
} if (per1.compareTo(per2)>0)
System.out.println(per1.getNombre()+
. . .
" es mayor que: "+ per2.getNombre());
public String toString(){ }
}
return apellido+", "+nombre;
}
public int compareTo(Persona o){
return this.edad - o.edad;
}
}

AyED - Cursada 2021 Laura Fava - Pablo Iuliano


La interface Comparable<T> en
Árboles Binarios de Búsqueda
y HEAP

El código de esta presentación es a nivel informativo.


No se implementarán estas estructuras en la práctica.

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


Árboles Binarios de Búsqueda
Estructura

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


Árboles Binarios de Búsqueda- Estructura
public class ArbolBinarioDeBusqueda<T extends Comparable<T>> {
private T dato;
private ArbolBinarioDeBusqueda<T> hijoIzquierdo;
private ArbolBinarioDeBusqueda<T> hijoDerecho;

private ArbolBinarioDeBusqueda() {
}
public ArbolBinarioDeBusqueda(T dato) {
this.dato = dato;
}

public T getDato() {
return dato;
}
public void setDato(T dato) {
this.dato = dato;
}

public ArbolBinarioDeBusqueda<T> getHijoIzquierdo() {


return this.getHijoIzquierdo();
}
public ArbolBinarioDeBusqueda<T> getHijoDerecho() {
return this.getHijoDerecho();
}
. . .
}

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


Árboles Binarios de Búsqueda
Ejemplos de instanciación y uso de árboles binarios de búsqueda con diferentes tipos:
ArbolBinarioDeBusqueda<Integer> abb = new ArbolBinarioDeBusqueda<Integer>();
abb.insertar(new Integer(2));
abb.insertar(6);
abb.insertar(1);
Clases que
abb.insertar(13); implementan la
abb.insertar(5); interface Comparabe

ArbolBinarioDeBusqueda<Persona> abb = new ArbolBinarioDeBusqueda<Persona>();


Persona p = new Persona(“Paula",“Gomez",16);
abb.insertar(p);
p = new Persona(“Ana",“Rios",6);
abb.insertar(p);
p = new Persona(“Maria",“Ferrer",55);
abb.insertar(p);
Alumno a = new Alumno(“Luis”, “Rios”, 18); // Alumno subclase de Persona
Abb.insertar(a);

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


Árboles Binarios de Búsqueda
Inserción de un dato (Weiss)
package ayed2021;

public class ArbolBinarioDeBusqueda<T extends Comparable<T>> {


private T dato;
private ArbolBinarioDeBusqueda<T> hijoIzquierdo;
private ArbolBinarioDeBusqueda<T> hijoDerecho;
. . .
public void agregar(T x) {
if (dato == null) ArbolBinarioDeBusqueda<Integer> ab
dato = x; b =
new ArbolBinarioDeBusqueda<Integer>()
else
abb.insertar(2);abb.insertar(6);
this.agregar(x, this);
abb.insertar(1);
} abb.insertar(13);
private void agregar(T x, ArbolBinarioDeBusqueda<T> t) { abb.insertar(5);
if (x.compareTo(t.getDato()) < 0) abb.insertar(7);
if (t.getHijoIzquierdo() == null) abb.insertar(5);
abb.mostrar();
t.setHijoIzquierdo(new ArbolBinarioDeBusqueda<T>(x));
else
this.agregar(x, t.getHijoIzquierdo());
else if (x.compareTo(t.getDato()) > 0)
if (t.getHijoDerecho() == null)
t.setHijoDerecho(new ArbolBinarioDeBusqueda<T>(x));
else
this.agregar(x, t.getHijoDerecho());
}
}

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


Colas de Prioridad
En las colas de prioridad, el orden lógico de sus elementos está determinado por la
prioridad de los mismos. Los elementos de mayor prioridad están en el frente de la cola y
los de menor prioridad están al final. De esta manera, cuando se encola un elemento,
puede suceder que éste se mueva hasta el comienzo de la cola.
Hay varias implementaciones de cola de prioridad (listas ordenadas, listas desordenadas,
ABB, etc.) pero la manera clásica es utilizar una heap binaria. La heap binaria implementa
la cola usando un árbol binario que permite encolar y desencolar con un O(log n) y debe
cumplir dos propiedades:
- propiedad estructural: ser un árbol binario completo de altura h, es decir, un árbol
binario lleno de altura h-1 y en el nivel h, los nodos se completan de izquierda a derecha.
- propiedad de orden: El elemento máximo (en MaxHeap) está almacenado en la raíz y el
dato almacenado en cada nodo es mayor o igual al de sus hijos (en MinHeap es inverso).

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


Colas de Prioridad
Usando un arreglo para almacenar los elementos, podemos usar algunas propiedades para
determinar, dado un elemento, el lugar donde están sus hijos o su padre.

La raíz está almacenada en la posición 1

El hijo izquierdo está en la posición 2*i


El hijo derecho está en la posición 2*i + 1
El padre está en la posición [i/2]

Hay dos tipo de heaps: MinHeap y MaxHeap.


MinHeap: el valor de la raíz es menor que el valor de sus hijos y éstos son raíces de
minHeaps
MaxHeap: el valor de la raíz es mayor que el valor de sus hijos y éstos son raíces de
maxHeaps.
Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano
Cola de Prioridades - HEAPs
Podríamos tener múltiples implementaciones de
la interface ColaPrioridades<T> usando,
por ejemplo, listas ordenadas, listas
desordenadas, ABB, etc.
Esta implementación usa un árbol binario
mapeado en un arreglo para implementar Colas
de Prioridades -> HEAPs

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


MaxHeap
Constructores
package heap;
En java no se puede crear un arreglo de elementos T:
public class MaxHeap<T extends Comparable<T>> private T[] datos = new T[100];
implemnets ColaPrioridades<T> Una opción es crear un arreglo de Comparable y
{ castearlo:
private T[] datos = (T[]) new Comparable[100]; private T[] datos=(T[]) new Comparable[100];
private int cantEltos = 0;

public MaxHeap() {}

public MaxHeap(ListaGenerica<T> lista){ O(n.log n)


lista.comenzar(); En este constructor se recibe la lista, se recorre y
while(!lista.fin()){ para cada elemento se agrega y se filtra. El
this.agregar(lista.proximo()); agregar es el método de la HEAP. El agregar()
} invoca al percolate_up().

public MaxHeap(T[] elementos) {


for (int i=0; i<elementos.length; i++) {
cantEltos++; Orden lineal
datos[cantEltos] = elementos[i]; En este constructor, después de agregar todos los
} elementos en la heap, en el orden en que vienen
for (int i=cantEltos/2; i>0; i--) en el arreglo enviado por parámetro, restaura la
this.percolate_down(i); propiedad de orden intercambiando el dato de
cada nodo hacia abajo a lo largo del camino que
}
contiene los hijos máximos invocando al método
. . . percolate_down().
}

Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano


HEAP
Insertar/Agregar un
elementoEl dato se inserta como último ítem en la heap. La
package heap;
propiedad de orden de la heap se puede romper.
public class Heap<T extends Comparable<T>> Se debe hacer un filtrado hacia arriba para
implemnets ColaPrioridades<T> restaurar la propiedad de orden.
{
private T[] datos = (T[]) new Comparable[100];
private int cantEltos = 0;

public boolean agregar(T elemento) {


this.cantEltos++;
this.datos[cantEltos] = elemento;
this.percolate_up(cantEltos);
return true;
}
Hay que intercambiar el 31 con el 12 y después
con el 17 porque 31 es mayor que ambos. El
private void percolate_up(int indice) {
último intercambio (c), no se realiza porque 31 es
T temporal = datos[indice];
menor que 42.
while (indice/2>0
&&
datos[indice/2].compareTo(temporal)<0){
datos[indice] = datos[indice/2];
indice = indice/2;
}
El filtrado hacia arriba restaura la propiedad de
datos[indice] = temporal;
orden intercambiando el elemento insertado a lo
}
largo del camino hacia arriba desde el lugar de
. . .
}
inserción
Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano
HEAP
Filtrado hacia abajo: percolate_down
Para filtra
r:
package heap; m ayor de lo se elige el
lo comp s hijos y se
public class MaxHeap<T extends Comparable<T>> ara con
padre. el
implemnets ColaPrioridades<T> { percolate_down(3
private T[] datos = (T[]) new Comparable[100]; )
private int cantEltos = 0;
. . .
private void percolate_down(int posicion) {
T candidato = datos[posicion];
boolean detener_percolate = false;
while (2 * posicion <= cantEltos && !detener_percolate) {
//buscar el hijo maximo de candidato (hijo_máximo es el indice)
percolate_down(2
int hijo_maximo = 2 * posicion; )
if (hijo_maximo != this.cantEltos){ //hay mas eltos, tiene
hderecho
4
if (datos[hijo_maximo + 1].compareTo(datos[hijo_maximo]) > 0)
2
{
hijo_maximo++;
} 16
} percolate_down(1
if (candidato.compareTo(datos[hijo_maximo]) < 0) { //padre<hijo )
4
datos[posicion] = datos[hijo_maximo]; 2
posicion = hijo_maximo;
} else { 1 1
detener_percolate = true; 5 6
}
}
this.datos[posicion] = candidato;
} 1
. . . 5
}
Algoritmos y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano
HEAP
Eliminar máximo – tope()
package heap; Para extraer un elemento de la heap hay que moverlo
public class Heap<T extends Comparable<T>>
a una variable temporal, mover el último elemento de
implemnets la heap al hueco, y hacerlo bajar mediante
ColaPrioridades<T>{ intercambios hasta restablecer la propiedad de orden
private T[] datos = (T[]) new (cada nodo debe ser mayor o igual que sus
Comparable[100]; descendientes).
private int cantEltos = 0;

public T eliminar() {
if (this.cantElto > 0) {
T elemento = this.datos[1];
this.datos[1] = this.datos[this.cantEltos];
this.cantEltos--;
this.percolate_down(1);
return elemento;
}
return null;
}

public T tope() {
return this.datos[1]; En el arreglo se ve así:
}

public boolean esVacia() {


if (this.cantEltos>0) {
return false;
}
return true;
}
. . .
Algoritmos
} y Estructuras de Datos - Cursada 2021 Laura Fava - Pablo Iuliano

También podría gustarte