Está en la página 1de 228

Tema 3: Propiedades básicas de la Orientación a

Objetos
Diseño Software (614G01015)

Eduardo Mosqueira Rey (Coordinador)

Departamento de Ciencias de la Computación y Tecnologı́as de la Información


Facultad de Informática
Abstracción y Encapsulamiento
Modularidad
Jerarquı́a
Polimorfismo
Tipificación
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento

2 Modularidad

3 Jerarquı́a

4 Polimorfismo

5 Tipificación

6 Ligadura Dinámica

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 2


Abstracción y Encapsulamiento
Modularidad
Jerarquı́a Abstracción
Polimorfismo Encapsulamiento
Tipificación
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento
Abstracción
Encapsulamiento

2 Modularidad

3 Jerarquı́a

4 Polimorfismo

5 Tipificación

6 Ligadura Dinámica

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 3


Abstracción y Encapsulamiento
Modularidad
Jerarquı́a Abstracción
Polimorfismo Encapsulamiento
Tipificación
Ligadura Dinámica

Abstracción
Abstracción
Representación de las caracterı́sticas fundamentales de algo sin incluir
antecedentes o detalles irrelevantes.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 4


Abstracción y Encapsulamiento
Modularidad
Jerarquı́a Abstracción
Polimorfismo Encapsulamiento
Tipificación
Ligadura Dinámica

Abstracción

Es uno de los métodos fundamentales para enfrentarse a la


complejidad inherente al software (ya visto en los TADs).
El elemento clave de la abstracción en la Orientación a Objetos es la
clase.
Una clase describe un grupo de objetos identificando su estado y
comportamiento.
Ejemplo: Esfera
Estado: Coordenadas del centro y radio.
Comportamiento: Mover el centro, modificar el radio, area,
perı́metro, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 5


Abstracción y Encapsulamiento
Modularidad
Jerarquı́a Abstracción
Polimorfismo Encapsulamiento
Tipificación
Ligadura Dinámica

Encapsulamiento
Encapsulamiento
Proceso de ocultación al exterior de aquellos detalles de la
implementación de un objeto que no es necesario conocer para su uso.

En ocasiones también se usa para hacer referencia al proceso de


almacenar en un mismo compartimiento los elementos de una
abstracción que constituyen su estructura y su comportamiento.
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 6
Abstracción y Encapsulamiento
Modularidad
Jerarquı́a Abstracción
Polimorfismo Encapsulamiento
Tipificación
Ligadura Dinámica

Abstracción vs. Encapsulamiento

Son conceptos complementarios.


La abstracción se centra en el comportamiento observable de un
objeto.
El encapsulamiento se centra en cómo implementar el objeto que da
lugar a ese comportamiento (especificadores de visibilidad, etc.).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 7


Abstracción y Encapsulamiento
Modularidad
Jerarquı́a Abstracción
Polimorfismo Encapsulamiento
Tipificación
Ligadura Dinámica

Ventajas

Ocultación de la información
La supresión de los detalles de bajo nivel nos permite razonar acerca
de la operación u objeto de forma más eficiente.
Un cambio en la representación interna, si no afecta a la parte
pública de un objeto, no afectará a los clientes que usen dicho objeto
(ej. cambiar la implementación de una función por otra más
eficiente).
Representación conjunta de estado y comportamiento
Todo lo relacionado con un objeto determinado está situado en la
clase software que representa a ese objeto ⇒ naturalidad,
simplicidad, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 8


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento

2 Modularidad
Definición y Caracterı́sticas
Modularidad en Java
Paquetes Java
Objetivos de los Paquetes

3 Jerarquı́a

4 Polimorfismo

5 Tipificación

6 Ligadura Dinámica
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 9
Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Modularidad
Modularidad
Propiedad que tiene un sistema que ha sido descompuesto en un
conjunto de partes o módulos que sean cohesivos (guardan cierta relación
lógica) y débilmente acoplados (minimizan sus dependencias).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 10


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Ventajas

Ventajas
El hecho de fragmentar un programa en componentes individuales
suele contribuir a reducir su complejidad.
Permite crear una serie de fronteras bien definidas y dentro del
programa ⇒ aumenta la comprensión del mismo.
Relación con el encapsulamiento
Los módulos pueden ocultar información a otros módulos actuando
como mecanismos de encapsulamiento a un nivel superior al
encapsulamiento de las propias clases.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 11


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Modularidad en Java

La modularidad se organiza en Java Estructura lógica Estructura física

de forma lógica en clases y


Paquete Directorio
paquetes y de forma fı́sica
mediante ficheros y directorios. Clase
Fichero
.java
Clases:
Clase
Encapsulan los atributos y Fichero
.java
métodos de un tipo de objetos en Clase
un solo compartimiento.
Ocultan, mediante los
Paquete Directorio
especificadores de acceso, los
elementos internos que no se Clase
Fichero
pretende publicar al exterior. .java

Esta protección es altamente Clase

configurable al existir varios


niveles de acceso.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 12


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Modularidad en Java
Ficheros Java
Actúan como unidades fı́sicas de compilación.

Ficheros y clases Java: Dentro de un fichero .java pueden residir


varias clases con las siguientes restricciones:
Sólo puede haber una clase pública por fichero.
El nombre del fichero debe ser el mismo que el de la clase pública.
Si no existe ninguna clase pública tampoco existe ninguna restricción
con respecto al nombre del fichero.
Compilación de ficheros
La compilación de un fichero .java genera tantos ficheros .class
(bytecodes) como clases existen en dicho fichero.
Por simplicidad muchas veces se recomienda que un fichero
contenga sólo una única clase (es más claro y facilita que los
entornos de desarrollo recompilen adecuadamente los ficheros .java
con una fecha posterior a su correspondiente .class).
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 13
Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Modularidad en Java
Paquetes Java
Son unidades lógicas de agrupación de clases.
Ocultación de información: Las clases que no son públicas solo son
visibles dentro del propio paquete.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 14


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Definición de paquetes

Se utiliza la directiva package al Paquete Java


principio de cada fichero // Fichero Circulo.java
Todas las clases definidas en ese
package graficos;
fichero se consideran que
pertenecen a ese paquete public class Circulo {
private int radio;
En caso de que no se especifique se
considera que todas las clases se public int getRadio() {
return radio;
encuentran en el paquete por }
defecto (aunque se recomienda no
public void setRadio(int radio) {
usarlo) this.radio=radio;
Los nombres de los paquetes suelen }

ir en minúsculas (sin notación //...


“Camel Case”) }

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 15


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Importación de paquetes

El nombre de una clase es siempre el nombre de su paquete + un


punto + el propio nombre de la clase: graficos.Circulo
Para usar una clase habrı́a que anteponer siempre el nombre del
paquete

Uso de clases y paquetes sin import

graficos.Circulo c1 = new graficos.Circulo();

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 16


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Importación de paquetes
La sentencia import
Especifica que los contenidos públicos del paquete especificado entran en
el espacio de nombres del fichero de origen

De esta forma podemos usar el nombre de la clase sin anteponer el


nombre del paquete
La importación se especifica justo después de la declaración
package
Uso de clases y paquetes con import

package otropaquete;
import graficos.Circulo;

// ...

Circulo c1 = new Circulo(); // No necesitamos anteponer el nombre del


// paquete al haber importado la clase

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 17


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Importación de paquetes
Formas de importación:
Importar una clase concreta
Importar todas las clases públicas de un paquete

Distintas formas de importación

package otropaquete;
import graficos.Circulo; // Importa solo la clase Circulo
import graficos.*; // Importa todas las clases públicas del paquete

Se recomienda usar la primera porque es más clara de cara al


desarrollador (queda perfectamente detallado qué clases estamos
usando y cuáles no)
La importación de clases concretas crea listas largas al principio de
las clases pero los IDEs modernos permiten mantenerlas de forma
sencilla (sugieren los paquetes que faltan, avisan de importaciones
no usadas, etc.)
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 18
Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Manejo de paquetes en IntelliJ IDEA


Usando el menú contextual con Alt+Intro o pulsando en las
bombillas que aparecen podemos incluir los paquetes que nos
faltan...

... u optimizar los imports para eliminar aquellos no deseados.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 19


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Importación de paquetes

Importante...
No es necesario incluir la sentencia import para dar privilegios de
acceso de un paquete a otro

Un import no es un uses de Pascal o un include de C.


Siempre podremos tener acceso a una clase usando su nombre
cualificado completo paquete.Clase sin necesidad de hacer el
import
Sólo se requiere que la clase sea pública y esté accesible en el
CLASSPATH
Por comodidad las clases pertenecientes al paquete java.lang
(Object, etc.) no es necesario importarlas o usar su nombre
completo para poder usarlas

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 20


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Jerarquı́as de paquetes

Los nombres de los paquetes pueden tener varios niveles separados


por puntos
Ejemplo: java.util,java.util.jar, etc.

Importante...
Aunque el nombre del paquete puede tener varios niveles no existe el
concepto de “subpaquete” ni relaciones jerárquicas entre los paquetes

Se trata de una relación jerárquica de nombres por motivos de


organización y claridad
La relación entre java.util y java.util.jar es la misma que
entre java.util y java.swing ⇒ Son dos paquetes distintos

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 21


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Objetivos de los paquetes

1 Diseñar un dispositivo de modularidad superior a las clases


Dentro de un paquete existen clases públicas (visibles al exterior) y
clases no públicas (destinadas a ser usadas dentro del paquete)
Se usa el modificador de visibilidad de las clases para establecer su
carácter
2 Agrupar clases con funcionalidades similares
3 Organizar fı́sicamente los ficheros fuente
4 Prevenir conflictos de nombre

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 22


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Objetivos de los paquetes


2 Agrupar clases con funcionalidades similares
Aunque nuestras clases sean todas públicas es común agrupar clases
relacionadas en paquetes para facilitar su organización
Ejemplo: Las clases del interfaz están en el paquete ui, la biblioteca
de palabras está en el paquete lib, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 23


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Objetivos de los paquetes


3 Organizar fı́sicamente los ficheros fuente
Java equipara los nombres de paquetes con los directorios en disco,
lo que permite tener organizados los ficheros fuente

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 24


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Polimorfismo Paquetes Java
Tipificación Objetivos de los Paquetes
Ligadura Dinámica

Objetivos de los paquetes

4 Prevenir conflictos de nombre


Los paquetes permiten minimizar los conflictos de nombre en clases
con nombres iguales, ya que el nombre de la clase siempre lleva
antepuesto el nombre del paquete
Ejemplo: En el API de Java existen nombres de clases iguales en
paquetes diferentes: java.awt.List y java.util.List
¿Cómo prevenimos los conflictos con los nombres de los
paquetes?
Para evitarlos existe el convenio de utilizar como prefijo a los
nombres de los paquetes los nombres invertidos del dominio de
Internet de la empresa que los ha desarrollado (que son únicos)
Ejemplo: los paquetes de Eclipse tienen el prefijo org.eclipse, los
paquetes de Google tienen el prefijo com.google, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 25


Abstracción y Encapsulamiento
Modularidad Definición y Caracterı́sticas
Jerarquı́a Modularidad en Java
Paquetes Java
Polimorfismo
Objetivos de los Paquetes
Los módulos de Java
Tipificación
Ligadura Dinámica 9 no forman parte
de esta asignatura,
Los nuevos módulos de Java 9... ası́ que... ¡olvı́date
de esta diapositiva!

Los módulos añaden un nivel más de


modularidad por encima de los paquetes.
Configuración fiable: Los módulos
proporcionan mecanismos para declarar
explı́citamente sus dependencias.
Encapsulamiento fuerte: Los paquetes
de un módulo son accesibles a otros
módulos sólo si el módulo los exporta
explı́citamente.
Plataforma Java escalable: La
plataforma está modularizada y se pueden
crear runtimes personalizados que incluyan
solo los módulos necesarios.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 26


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento

2 Modularidad

3 Jerarquı́a
Composición
Herencia
Clases Abstractas
Interfaces
Herencia vs. Composición

4 Polimorfismo

5 Tipificación

6 Ligadura Dinámica
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 27
Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Jerarquı́a

Jerarquı́a
Una jerarquı́a es una clasificación de las abstracciones

Existen dos tipos de jerarquı́as en la programación orientada a


objetos:
Composición
Herencia

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 28


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Composición
Composición
Define relaciones TIENE UN y ocurre cuando un elemento contiene otros
elementos (los objetos incluyen otros objetos en la definición de su
estado).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 29


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Composición

Objeto simple

public class Direccion {


String calle;
Los objetos más simples tienen int numero;
String piso;
su estado compuesto de tipos String ciudad;
primitivos (int, float, etc.) u int codigoPostal;
String pais;
otros objetos que juegan un rol
similar a los tipos primitivos public String toString()
{
(String, Date, return calle + " " + numero +
BigDecimal, etc.) " " + piso + ", " +
codigoPostal + " " +
ciudad + ", " + pais;
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 30


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Composición

Objeto compuesto

Los objetos compuestos incluyen public class Persona {


también en su estado a otros String nombre;
String apellidos;
objetos (en este caso String telefono;
String email;
Direccion) int edad;
Habitualmente los objetos Direccion direccion;

compuestos reciben peticiones public String nombreCompleto() {


cuya resolución se delega a }
return nombre + " " + apellidos;

alguno de los objetos internos


(ej. direccionFisica) ⇒ public String direccionFisica() {
Mecanismo de Delegación return direccion.toString();
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 31


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia
Herencia
Relación ES UN entre clases, en las que una clase hereda la estructura y
el comportamiento definidos en una o más clases.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 32


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia

Funcionamiento
Una subclase hereda de una o más superclases y aumenta o redefine
la estructura y el comportamiento de dichas superclases.
Generalización vs. Especialización
Las subclases representan conceptos especializados.
Las superclases representan generalizaciones de los aspectos comunes
de las subclases.
Según como se lea la relación de herencia puede ser vista como una
generalización o una especialización.
En Java
La herencia se especifica usando la cláusula extends al principio de
la definición de una clase.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 33


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Ejemplo de herencia

Estudiante hereda de Persona


y hereda sus atributos y métodos.
Atributos heredados de Persona:
nombre, apellidos, Herencia (clase Estudiante)
telefono, email, edad y
direccion. public class Estudiante extends Persona {
Titulacion titulacion;
Atributos propios: Asignatura [] asignaturas;
titulacion y asignaturas. public int calcularMatricula() {
Métodos heredados de Persona: }
// ...

nombreCompleto y
direccionFisica.
Métodos propios:
calcularMatricula.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 34


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Ejemplo de herencia

Profesor hereda de Persona y


hereda sus atributos y métodos.
Atributos heredados de Persona:
nombre, apellidos, Herencia (clase Persona)
telefono, email, edad y
public class Profesor extends Persona {
direccion. String departamento;
Atributos propios: String categoria;
String decicacion;
departamento, categoria, java.util.Date antiguedad;
dedicacion y antiguedad.
public int calcularSueldo() {
Métodos heredados de Persona: // ...
}
nombreCompleto y
direccionFisica.
Métodos propios:
calcularSueldo.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 35


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Aspectos a tener en cuenta en la herencia

Tanto Estudiante como Profesor tienen una relación ES UN


con Persona.
Eso quiere decir que tanto Estudiante como Profesor son
personas y pueden ser usadas allı́ donde se requiere un objeto de
tipo. Persona ⇒ Polimorfismo de inclusión que comentaremos
más adelante.
Internamente los elementos definidos en una superclase aparecen
siempre en la misma posición en las subsecuentes subclases.
nombre será el primer atributo y nombreCompleto el primer
método, tanto en Estudiante como en Profesor.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 36


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Aspectos a tener en cuenta en la herencia


Un objeto de una subclase siempre tiene en su interior un objeto de
su superclase.

Estudiante Profesor

Persona Persona

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 37


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Estructuras de herencia

Las estructura final de las relaciones de herencia depende de


aspectos como la herencia simple o múltiple y las clases raı́z:

Herencia simple
Cada clase tiene, como máximo, un ancestro.

Lenguajes:
Java, Object Pascal, C#, etc.
Ventajas:
Las estructuras de herencia son sencillas y tienen forma de árbol.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 38


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Estructuras de herencia
Clase raı́z
Clase que actúa como superclase del
resto de clases. Object

En combinación con la herencia


simple genera una estructura de
árbol con una raı́z única.
Es la estructura propia de Java Persona Animal

en la que la clase raı́z es la clase


Object.
Si no se incluye la cláusula
extends en la definición de Estudiante Profesor Perro Gato
una clase se sobreentiende que
está heredando directamente de
Object.
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 39
Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Estructuras de herencia

El gráfico anterior debe rehacerse ahora como:

Estudiante Profesor

Persona Persona

Object Object

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 40


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Estructuras de herencia
Herencia múltiple
Una clase puede heredar de varias clases simultáneamente.

Lenguajes:
C++, Eiffel, etc.
Ventajas:
Una clase puede heredar caracterı́sticas de varias superclases no
relacionadas ⇒ más posibilidades de diseño.
Inconvenientes:
Genera conflictos cuya resolución es especı́fica de cada lenguaje ⇒
aumenta la complejidad de la programación y reduce la
comprensibilidad.
La tendencia actual es evitar la herencia múltiple ya que es posible
desarrollar jerarquı́as de herencia complejas y flexibles con herencia
simple ⇒ ver Interfaces.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 41


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia y constructores
¿Qué constructor hay en SubClase?
Un objeto de una subclase tiene
class SuperClase { siempre un objeto de una
private int valor;
superclase dentro.
public SuperClase(int valor) { Antes de crear el objeto de la
this.valor = valor;
} subclase se crea primero el
} objeto de la superclase
class SubClase extends SuperClase { La palabra clave super se usa
private int subvalor;
// Constructor ? para llamar a los constructores
de la superclase (como this se
usaba para llamar a otro
constructor de la misma clase).
No se puede usar super() y
this() en un mismo
constructor.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 42


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Clases abstractas
Clase abstracta
Clase que no pueden ser instanciada (no se puede crear un objeto de
la misma) y que está destinada a ser extendida por herencia.
En Java se crea anteponiendo abstract a class.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 43


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Objetivos de las clases abstractas

Ejemplo
1 Definir clases generales que public abstract class Animal {
agrupan caracterı́sticas comunes private String nombre;
private String codigo;
Son clases destinadas a la private Date fechaNacimiento;
herencia y de las cuales no tiene
sentido que existan instancias. public String getNombre()
{ return nombre; }
P. ej. una tienda de animales }
agrupa las caracterı́sticas
comunes de todos en la clase public class Gato extends Animal {
Animal. public enum variedadGato
{SIAMES, ESFINGE};
No tiene sentido que existan }
instancias de Animal pero si de
las subclases concretas (Gato, public class Perro extends Animal {
public enum variedadPerro
Perro, etc.). {PASTOR_ALEMAN, LABRADOR};
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 44


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Métodos abstractos

Método abstracto
Método en el que sólo se define su interfaz (nombre, parámetros y tipo
de retorno) pero no su implementación (que se difiere a las subclases).

Aspectos a tener en cuenta:


Se definen en Java anteponiendo la palabra clave abstract.
Un método abstracto sólo puede pertenecer a una clase abstracta,
pero una clase abstracta puede tener métodos NO abstractos.
Las subclases de una clase abstracta deben implementar los métodos
abstractos o declararse como abstractas.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 45


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Objetivos de las clases abstractas

Ejemplo
2 Diferir comportamiento a las
subclases public abstract class Figura {
Hay métodos cuyo interfaz public abstract double area();
public abstract double perimetro();
podemos definir en la superclase }
pero cuya implementación es
propia de cada una de las public class Circulo extends Figura {
private double radio;
subclases. public double area() {
P. ej. podemos definir un método return Math.PI*radio*radio;
}
abstracto area() en Figura
pero la implementación del public double perimetro() {
método dependerá de cada figura return 2*Math.PI*radio;
}
en concreto (Circulo, // ...
Rectangulo, etc.). }

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 46


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Objetivos de las clases abstractas

3 Asegurar la consistencia en el
Ejemplo
interfaz de todas las subclases
Las subclases están obligadas a public abstract class Figura {
implementar los métodos public abstract double area();
public abstract double perimetro();
heredados de una clase abstracta, }
eso permite asegurar que todas
las subclases tienen una class Rectangulo extends Figura {
private double base;
implementación de dicho método private double altura;
con el interfaz definido en la public double area() {
superclase. return base*altura;
}
P.ej. Al indicar que la clase
Rectangulo hereda de Figura public double perimetro() {
return (base*2)+(altura*2);
el compilador obliga a la primera }
a dar una implementación a los // ...
métodos area() y }
perimetro().

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 47


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Clases abstractas
Las clases abstractas pueden incluir elementos no abstractos

public abstract class Figura {


private int x; // Coordenadas de la figura
private int y;

public void moverA(int x, int y) {


this.x = x;
this.y = y; El método moverA actúa co-
} mo método de escritura de
las propiedades x e y y es
public int getX() {
común a todas las figuras
return x;
}

public int getY() {


return y; Los métodos getX y getY
} actúan como métodos de lec-
tura y también son comunes
public abstract double area();
public abstract double perimetro();
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 48


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces
Interfaces
Son clases abstractas “puras” que definen un protocolo de conducta pero
no cómo debe implementarse dicha conducta.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 49


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces en Java

Se definen con la palabra clave interface y no class.


Contienen las cabeceras de métodos que son, implı́citamente,
públicos y abstractos, por lo que no incluyen los cuerpos de dichos
métodos.
Pueden contener atributos pero serán implı́citamente públicos,
estáticos y finales, es decir, constantes de clase.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 50


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces en Java

Declaración de un interfaz
[public] interface Nombre [extends superinterfaz, ...]
{ // Constantes de clase // Métodos abstractos }

Ejemplo de interfaz

public interface Figura {


double area(); // Método public y abstract de forma implı́cita
double perimetro(); // Método public y abstract de forma implı́cita
}

En principio un interfaz no se diferencia mucho de una clase


abstracta con todos sus métodos abstractos.
Y perdemos la capacidad de incluir atributos y métodos no
abstractos ¿Qué utilidad tienen entonces?

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 51


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia entre interfaces


Herencia entre interfaces
Un interfaz puede heredar de otros interfaces (incluye herencia múltiple),
pero nunca de una clase.

Ejemplo
Monstruo
interface Monstruo {
void amenaza();
}
interface MonstruoPeligroso extends Monstruo {
void destruye();
Monstruo
} Letal
Peligroso
interface Letal {
void mata();
}
interface Vampiro extends MonstruoPeligroso,
Letal {
void bebeSangre(); Vampiro
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 52


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia entre interfaces

En este caso la herencia múltiple no es un problema ya que los


interfaces sólo tienen la cabecera de los métodos, no la
implementación, por lo que no se corre el riesgo de heredar
implementaciones diferentes para un mismo método.
En el ejemplo anterior en interfaz Vampiro tendrá los métodos:
amenaza, destruye, mata y bebeSangre.
La herencia de interfaces es paralela a la herencia entre clases.
La conexión entre ambas jerarquı́as de herencia se hace mediante el
proceso de implementación de interfaces.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 53


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Implementación de interfaces
Implementación de interfaces
Implementar un interfaz consiste en darle una implementación concreta a
todos y cada uno de los métodos que contiene.

Ejemplo

public interface Figura { La implementación se hace a través


double area();
double perimetro(); de la palabra clave implements.
}
Una clase que implementa un
class Circulo implements Figura { interfaz está obligada a darle una
private double radio;
public double area() { implementación a todos los
return Math.PI*radio*radio; métodos del interfaz (Circulo
}
public double perimetro() { debe implementar area() y
return 2*Math.PI*radio; perimetro()).
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 54


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Implementación de interfaces
Las clases pueden implementar múltiples interfaces.

Monstruo

Ejemplo

class Virus implements Monstruo, Letal {


public void amenaza() { Monstruo
Letal
// Contagio del virus Peligroso
}

public void mata() {


// Enfermedad del virus
} Vampiro
}

Virus

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 55


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Implementación de interfaces

Una clase puede evitar dar una implementación a los métodos del
interfaz declarándose abstracta.

Ejemplo

abstract class AbstractVirus implements Monstruo, Letal {


// Puede obviar la implementación de los interfaces
}

class Ebola extends AbstractVirus {


public void amenaza() {
// Las clases concretas sı́ estan obligadas a dar una implementación
}

public void mata() {


// ...
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 56


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Implementación de interfaces

También podemos realizar una implementación temporal y dejar la


implementación definitiva para más adelante.
¡Ojo! puede ser peligroso ⇒ ver Tema 5: Herencia de Limitación

Ejemplo

class Gozilla implements MonstruoPeligroso {


public void destruye() {
throw new UnsupportedOperationException("Not supported yet.");
}

public void amenaza() {


throw new UnsupportedOperationException("Not supported yet.");
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 57


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Jerarquı́as de clases e interfaces


Herencia entre clases Implementación de interfaces

Herencia simple con una clase raíz Implementación múltiple de


(Object) clases a interfaces

Object Monstruo

Organismo Monstruo
Vivo Letal
Peligroso

Animales Virus Vampiro

Serpiente
Dracula Herencia entre interfaces
Cascabel
Herencia múltiple sin clase raíz

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 58


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Usos de los interfaces

Usos tı́picos de los interfaces


1 Revelar el interfaz de programación de un objeto sin revelar su clase.
2 Capturar las similitudes entre clases no relacionadas.
3 Definir nuevos tipos de datos.

Usos poco recomendados de los interfaces


4 Marcadores de clase. Para comprender bien
5 Contenedores de elementos globales. el código de los usos
tı́picos necesitaremos
acabar el Tema
3. Quedaros por
ahora con la idea
general de los mismos

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 59


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Usos tipicos de los interfaces

1 Revelar el interfaz de programación de un objeto sin revelar su


clase
Un interfaz revela un servicio que ofrece una clase, pero no indica
qué clase en concreto está ofreciendo dicho servicio.
Gracias a esa ignorancia de qué clase está realizando la
implementación, dicha clase puede ser cambiada dinámicamente sin
afectar al cliente que utiliza el servicio.
Ejemplo: Supongamos que definimos un interfaz para representar un
servicio de ordenación de array.

Interfaz Ordenacion
public interface Ordenacion {
void ordena(int[] array);
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 60


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Revelar el interfaz sin revelar la clase

Podemos definir ahora varias clases implementadoras de dicho


interfaz de ordenación. Cada una con sus caracterı́sticas, ventajas e
inconvenientes.

Clases implementadoras del interfaz Ordenacion

public class OrdenacionBurbuja implements Ordenacion {


public void ordena(int[] array) {
// Ordenación de la burbuja
}
}

public class OrdenacionQuicksort implements Ordenacion {


public void ordena(int[] array) {
// Ordenación Quicksort
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 61


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Revelar el interfaz sin revelar la clase


Una clase cliente puede desconocer qué algoritmo de ordenación
concreto usa. Y este algoritmo puede ser modificado dinámicamente.
Clases implementadoras del interfaz Ordenacion

public class Cliente {


private int[] array;
public Cliente(int[] array) { this.array = array; }

public void ordenaArray(Ordenacion algoritmo) {


algoritmo.ordena(array);
}
public static void main(String[] args) {
int[] array1 = {5, 9, 8, 4, 1, 3, 7, 2, 6};
int[] array2 = {3, 5, 1, 7, 8, 6, 2, 4, 9};

Cliente c1 = new Cliente(array1);


c1.ordenaArray(new OrdenacionBurbuja());

Cliente c2 = new Cliente(array2);


c2.ordenaArray(new OrdenacionQuiksort());
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 62


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Usos tipicos de los interfaces

2 Capturar las similitudes entre clases no relacionadas


Clases que no están relacionadas en absoluto a través de la herencia
pueden ser consideradas como instancias de la misma clase si
implementan el mismo interfaz.
Ejemplo: Supongamos que estamos realizando un juego de aventuras
y creamos un interfaz por cada acción que los personajes pueden
realizar (luchar, nadar, volar, etc.).

Interfaces representando acciones

public interface CanFight { void fight(); }

public interface CanSwim { void swim(); }

public interface CanFly { void fly(); }

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 63


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Capturar las similitudes entre clases no relacionadas


Los héroes del juego pueden realizar ciertas acciones, los monstruos
pueden realizar otras, etc.

Clase Hero
public class Hero implements
Clase Monster
CanFight, CanSwim, CanFly {
public class Monster implements
public void fight() { CanFight, CanFly {
System.out.println("A hero can fight");
} public void fight() {
System.out.println("Monster fight");
public void swim() { }
System.out.println("A hero can swim");
} public void fly() {
System.out.println("Monster fly");
public void fly() { }
System.out.println("A hero can fly"); }
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 64


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Capturar las similitudes entre clases no relacionadas


Una clase como Adventure puede tratar a los héroes y a los
monstruos como instancias de la misma clase (CanFight).
Si una clase implementa un interfaz se considera que un
objeto de esa clase es una instancia de dicho interfaz.
Clase Adventure
public class Adventure {
public static void fight(CanFight x) { x.fight(); }
public static void swim(CanSwim x) { x.swim(); }
public static void fly(CanFly x) { x.fly(); }

public static void main(String[] args) {


Hero johnMcClane = new Hero();
Monster godzilla = new Monster();

if (johnMcClane instanceof CanFight)


fight(johnMcClane);
if (godzilla instanceof CanFight)
fight(godzilla);
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 65


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Usos tipicos de los interfaces


3 Definir nuevos tipos de datos
Un interfaz representa un nuevo tipo de datos.
En cualquier momento podemos añadir nuevas instancias diferentes
de dicho tipo de datos simplemente definiendo nuevas clases
implementadoras del interfaz.
Ejemplo: La clase Scanner del API de Java permite realizar análisis
sintácticos usando expresiones regulares.
El constructor de Scanner admite objetos de las clases String,
File, InputStream. Pero también admite objetos que
implementen el interfaz Readable.

Clase Scanner
public class Scanner {
public Scanner(String source) { ... };
public Scanner(File source) throws FileNotFoundException { ... }
public Scanner(InputStream source) { ... }
public Scanner(Readable source) { ... }
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 66


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Definir nuevos tipos de datos

El interfaz Readable representa objetos que son una fuente de


caracteres.
Estos caracteres son leı́dos mediante el método read y depositados
en un CharBuffer.
El método devuelve un entero con el número de caracteres
almacenados en el buffer o el valor -1 si se ha llegado al final de la
fuente.

Interfaz Readable
public interface Readable {
public int read(CharBuffer cb) throws IOException;
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 67


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Definir nuevos tipos de datos


Cualquier clase puede ahora implementar el interfaz Readable y ser
usada por la clase del API Scanner sin ningún tipo de problema.
Por ejemplo la clase RandomIP crea 4 números aleatorios de una IP.
Clase RandomIP
public class RandomIP implements Readable {
private int count = 4;
private static Random rand = new Random();

public int read(CharBuffer cb) {


if (count-- == 0) { return -1; }
String result = Integer.toString(rand.nextInt(255)) + " ";
cb.append(result);
return result.length();
}

public static void main(String[] args) {


Scanner s = new Scanner(new RandomIP());
while (s.hasNextInt()) { System.out.print(s.nextInt() + " "); }
} // Scanner usa el método read para leer objetos Readable
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 68


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Usos poco recomendados de los interfaces


4 Marcadores de clase
Un interfaz que se define sin incluir ningún método ni atributo es
conocido como un interfaz marcador de clase.
Como no incluye ningún elemento las clases que implementan este
interfaz no están obligadas a hacer nada (ni heredan nada) pero
quedan marcadas por dicho interfaz (se puede averiguar si lo
implementan usando el operador instanceof).

Ejemplo

public interface Cloneable { /* ¡VACÍO! */ }

public class ClaseClonable implements Cloneable {


// No esta obligada a hacer nada
public static void main(String[] args) {
ClaseClonable cc = new ClaseClonable();
if (cc instanceof Cloneable) {
// Comprobamos si un objeto es Cloneable
}
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 69


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Anotaciones vs. interfaces de marcado


Decimos que los interfaces de marcado no son un uso adecuado de
los interfaces porque, a partir de la versión 5 de Java existe un
mecanismo más útil para realizar ese marcado ⇒ las anotaciones.

Anotaciones
Son metadatos, es decir, información sobre los elementos del programa.
Son similares a las etiquetas del javadoc (como @author) pero
aplicadas al código, no a los comentarios.

Existen distintas anotaciones creadas en el API de Java


(@Override, @Deprecated, @SupressWarnings, etc.) pero
su verdadera potencia proviene de la posibilidad de crear anotaciones
personalizadas ⇒ Usado profusamente en librerias como JUnit, JPA,
etc.
Al contrario que con los interfaces, con las anotaciones se pueden
anotar no sólo clases sino también métodos o atributos.
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 70
Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

La anotación @Deprecated
Declara un método como depreciado para que el compilador avise de
que no debe usarse.
Es diferente a la misma anotación usada en Javadoc y que,
sorprendentemente, el compilador también leı́a (y lo sigue haciendo
por motivos de compatibilidad hacia atrás).
Actualmente se recomienda usar las dos anotaciones, una para los
comentarios y otra para el compilador.
La anotación @Deprecated
public class ClaseDeprecated {
/**
* Hace algo...
* @param valor sobre el que se hace algo
* @deprecated Usar mejor el método hacerAlgo
*/
@Deprecated public void hazAlgo(int valor) { }
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 71


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Anotaciones personalizadas
Creamos una anotación que registrará
Ejemplo el porcentaje de desarrollo de una cla-
se. Al marcarla como runtime pue-
de ser leida en tiempo de ejecución
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@interface EnDesarrollo { int porcentaje(); }

@EnDesarrollo (porcentaje=50)
class MiClase { }
Creamos una clase y marcamos su porcentaje
public class AnotacionSimple {
public static void main(String[] args) {
MiClase x = new MiClase();
Class c = x.getClass();
if (c.isAnnotationPresent(EnDesarrollo.class)) {
System.out.println("Esta clase esta en desarrollo");
EnDesarrollo ed =
(EnDesarrollo)c.getAnnotation(EnDesarrollo.class);
System.out.println("Porcentaje = " + ed.porcentaje());
}
}
} Podemos leer ese porcentaje en tiempo de ejecución

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 72


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Usos poco recomendados de los interfaces


5 Contenedores de elementos globales
En Java no existen variables globales, por dicho motivo los
programadores usan a veces a los interfaces como repositorios de
constantes.

Ejemplo

public interface Constantes {


double PI = 3.1415926;
int MAX_FILAS = 65536;
}

class Circulo implements Constantes {


private double radio;

public double area() {


// Heredamos PI del interfaz Constantes
return PI*radio*radio;
}
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 73


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces como contenedores de elementos globales

Problemas:
Los interfaces que implementa una clase es algo público y notorio,
estamos mostrando en dicho interfaz un aspecto de la
implementación (de donde obtenemos la constante PI) ⇒ Polución
del API exportado.
Estamos creando una dependencia entre Circulo y Constantes
que al ser pública puede no ser fácil de cambiar.
Soluciones:
Crear las constantes como tipos enumerados.
Crear las constante en clases relacionadas (MIN VALUE y
MAX VALUE están en la clase Integer).
Crear clases de utilidad para alojar dichas constantes (la clase Math
aloja constantes matemáticas como PI o E).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 74


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces como contenedores de elementos globales


Clases de utilidad como contenedores de constantes
public final class Math {
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;

// ...
}

class Circulo {
private double radio;

public double area() {


return Math.PI*radio*radio;
} Nuevo problema: en cada
si rota
uso de ladefuerit
constantetu pede
hay que
public double perimetro() { carpe diam. Mallorca
anteponer el nombre de la
return 2*Math.PI*radio;
} claseet(estamos
Menorca accediendo
illae sunt. a un
Mater
valor tua mala
estático burra clase)
de dicha est
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 75


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces como contenedores de elementos globales


Solución:
Utilizar la importación estática añadiendo static al import.
Es similar a la importación de clases pero en este caso importamos
elementos estáticos de las clases (atributos y métodos).

Clases de utilidad como contenedores de constantes


import static java.lang.Math.PI; // Importa solo la constante PI
import static java.lang.Math.*; // Importa todos los elementos estáticos

class Circulo {
private double radio;
Dos notaciones alternati-
vas: importar un elemento
public double area() { concreto o importar to-
return PI*radio*radio; dos los elementos estáticos
}
public double perimetro() {
return 2*PI*radio;
} Podemos usar los elemen-
// ... tos estáticos sin antepo-
} ner el nombre de la clase

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 76


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Interfaces como contenedores de elementos globales

Tened cuidado con:


El abuso del mecanismo de importación estática. Los elementos
importados aparentan ser de la propia clase cuando en realidad son
de otra ⇒ produce confusión.
Por lo tanto no abusar de la importación estática.
En caso de usarla optar preferentemente por la importación de
elementos concretos evitando usar la notación “*”.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 77


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

¿Interfaces o clases abstractas?


El API de colecciones utiliza ambos elementos conjuntamente

Interfaz
Collection
Clase abstracta

Clase concreta

Abstract
Set Queue List
Collection

Abstract Abstract Abstract


SortedSet Deque
Set Queue List

NavigableSet PriorityQueue ArrayDeque Abstract


ArrayList
SequentialList

TreeSet HashSet LinkedList

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 78


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Enumerados y clases abstractas

Los tipos enumerados en Java pueden definir métodos abstractos


siempre y cuando se de una implementación a dichos métodos
dentro de cada una de las constantes.

Tipo enumerado con implementaciones de un método en las constantes

public enum Animal {


CAT { public String makeNoise() { return "MEOW!"; } },
DOG { public String makeNoise() { return "WOOF!"; } };

public abstract String makeNoise();


}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 79


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Enumerados e interfaces

De la misma forma un tipo enumerado puede implementar un


interfaz.

Tipo enumerado implementando un interfaz

interface CanMakeNoise {
String makeNoise();
}

public enum Animal implements CanMakeNoise {


CAT { public String makeNoise() { return "MEOW!"; } },
DOG { public String makeNoise() { return "WOOF!"; } };
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 80


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Enumerados y colecciones

Existe una implementación de Set especı́ficamente dedicada a


trabajar con enumerados: EnumSet

Ejemplo de EnumSet

public class Text {


public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }

public void applyStyles(Set<Style> styles) { /* ... */ }

public static void main(String[] args) {


Text text = new Text();
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 81


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Enumerados y colecciones
Y también una implementación de Map especı́ficamente dedicada a
trabajar con enumerados: EnumMap

Ejemplo de EnumMap

enum DayOfWeek {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

class Main {
public static void main(String[] args) {
EnumMap<DayOfWeek, String> activityMap
= new EnumMap<>(DayOfWeek.class);
activityMap.put(DayOfWeek.MONDAY, "Soccer");
activityMap.put(DayOfWeek.TUESDAY, "Basketball");
// ...

System.out.println(activityMap.get(DayOfWeek.MONDAY)); // Soccer
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 82


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia vs. composición


Tanto la herencia como la composición pueden usarse como
mecanismos de reutilización, construyendo nuevas clases basándose
en clases ya creadas.
¿Qué deberı́amos usar? ¿Herencia o composición?

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 83


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia vs. composición

Ejemplo

Podrı́amos construir un public class Estudiante {


Titulacion titulacion;
Estudiante a partir de una Asignatura [] asignaturas;
Persona usando composición y no private Persona p;

herencia. public String nombreCompleto() {


return p.nombreCompleto();
Estudiante usarı́a delegación }
para llamar a los métodos de
public String direccionFisica() {
Persona. return p.direccionFisica();
}
¿Os parece una solución public int calcularMatricula() {
razonable? // ...
}

//...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 84


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia vs. composición


Existe un principio de diseño que dice “Favorece la composición
sobre la herencia”.
¿Por qué si a primera vista parece más incómoda teniendo que
escribir métodos de delegación?

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 85


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia vs. composición


Ejemplo

public class Stack extends Vector {


public Object push (Object item) {
addElement(item);
return item;
}
public synchronized Object pop() {
Contraejemplo: En el API de Java int len = size();
definieron una clase Stack que Object obj = peek();
removeElementAt(len - 1);
heredaba de una clase Vector. return obj;
}
Vector es una lista implementada public synchronized Object peek() {
con Arrays (similar a ArrayList). int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
public boolean empty() {
return size() == 0;
}
}
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 86
Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Qué inconvenientes existen en la clase Stack

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 87


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia vs. composición


Stack definido mediante composición
No existe confusión sobre los class Stack {
métodos que existen en Stack. private Vector datos;
public Stack () {datos = new Vector();}
No se rompe la encapsulación de la public boolean isEmpty () {
return datos.isEmpty();
pila (sólo se puede sacar el }
elemento que está en la cima). public Object push (Object item) {
datos.addElement (item);
No puede pasarse un Stack donde return item;
}
nos piden un Vector. public Object peek () {
Es muy fácil cambiar la clase }
return datos.lastElement();

Vector por una clase más public Object pop () {


moderna como Arraylist, al ser Object obj = datos.lastElement();
datos.removeElementAt
un elemento privado e interno sólo (datos.size()-1);
afectará a la propia clase. }
return obj;

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 88


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Ventajas de la herencia

Lleva implı́cito el principio de sustitución


Las subclases son instancias de las superclases y pueden pasarse ahı́
donde se pida una superclase.
El código a escribir es menor
Al heredar de una clase automáticamente heredamos sus métodos y
atributos. No necesitamos de mecanismos de delegación para acceder
a ellos (con lo que se evitan rellamadas).
Permite el acceso a elementos protegidos
La visibilidad protected está pensada para dar acceso a esos
elementos a las subclases, pero no a otras clases (esto cambia
ligeramente en Java ya que son visibles desde otras clases de un
mismo paquete).
Las relaciones entre clases son más públicas
Que una clase herede de otra forma parte de su interfaz público.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 89


Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Ventajas de la composición
La composición indica con claridad cuales son las operaciones
que podemos utilizar en la nueva estructura de datos definida
La herencia es menos clara de comprender porque obliga a analizar la
estructura de herencia para comprender mejor el funcionamiento de
la clase creada (“problema del yo-yo”).
La composición permite no “heredar” métodos indeseados (como
removeElementAt en Stack) .
La composición es más fácil de modificar
Si el objeto interno es privado es fácil cambiarlo por otro afectando
sólo a la clase local y no a otras clases que lo usen.
La composición no implica sustitución
La composición es una relación TIENE UN y no ES UN. Por lo que
evita el principio de sustitución propio de la herencia.
La composición es una solución más general
La herencia tiene limitaciones (herencia simple vs. múltiple) que no
tiene la composición (podemos crear una composición de varias
clases y usar sólo aquellos métodos que nos convengan).
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 90
Abstracción y Encapsulamiento Composición
Modularidad Herencia
Jerarquı́a Clases Abstractas
Polimorfismo Interfaces
Tipificación Herencia vs. Composición
Ligadura Dinámica

Herencia vs. composición

Conclusiones
Usar herencia exclusivamente en aquellas relaciones que claramente
corresponden a un tipo ES UN y en las que tiene sentido pasar un
elemento de la subclase como un elemento de la superclase.
Usar composición en aquellas relaciones que no se correspondan a
un tipo ES UN claro.
En caso de duda favorecer siempre la composición sobre la herencia.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 91


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento

2 Modularidad

3 Jerarquı́a

4 Polimorfismo
Tipos de Polimorfismo
Sobrecarga
Coacción
Polimorfismo de Inclusión
Polimorfismo Paramétrico

5 Tipificación

6 Ligadura Dinámica
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 92
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Polimorfismo
Polimorfismo
Capacidad de un objeto de pertenecer a más de una clase y de una
función de ser aplicada sobre parámetros de distintas clases.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 93


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clasificación de Cardelli y Wegner

Existen objetos (variables) que


pertenecen a distintas clases (tipos)

Existen funciones polimórficas que De Inclusión


usan el mismo código para tratar a
los objetos de distintas clases
Universal o
Verdadero

Paramétrico

Polimorfismo

Sobrecarga

El polimorfismo es sólo aparente


Ad Hoc o
Aparente
Las funciones realmente sólo tratan
parámetros de un único tipo pero Coacción
“simulan” aceptar varios tipos

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 94


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga
Sobrecarga (overloading)
Consiste en utilizar el mismo nombre para denotar métodos distintos
diferenciándolos por el número o tipo de los parámetros.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 95


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga

Ejemplo tı́pico: Sobrecarga en constructores

public class Caja {


private int lado; // Lado de la caja
private int valor; // Valor interno

// Constructores
public Caja() { this(0, 10); }

public Caja(int valor) { this(valor, 10); }

public Caja(Caja c) { this(c.valor, c.lado); }

public Caja(int valor, int lado) {


this.valor = valor;
this.lado = lado;
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 96


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga
El polimorfismo es sólo aparen-
Sobrecarga en otros métodos te, no existe una función que
acepte distintos parámetros,
public class Sobrecarga { sino distintas funciones que
public void metodoX (String s) { comparten el mismo nombre
System.out.println("Cadena " + s );
}

public void metodoX (int i) {


System.out.println("Entero " + i);
}

public void metodoX (int i, int j) {


System.out.println("Enteros " + i + " y " + j);
}

public void metodoX (int i, String c) {


System.out.println("Entero " + i + " y cadena " + c);
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 97


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga y tipos de retorno

¿Es el siguiente código válido?

public class Sobrecarga {


public int metodoX() {
return 1; // Devuelvo un int
}

public double metodoX() {


return 1.0; // Devuelvo un double
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 98


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga entre clases


Sobrecarga paramétrica
Sobrecarga que involucra a métodos de una misma clase que se
diferencian por el número y tipo de parámetros.

Sobrecarga entre clases


Sobrecarga que involucra a métodos situados en distintas clases y que
suelen tener los mismos parámetros (el “parámetro” que cambia es el
objeto sobre el que son llamados).

La sobrecarga entre clases se usa para dar nombres comunes a


operaciones comunes y facilitar el aprendizaje de bibliotecas de
funciones.
Ejemplo: un método como isEmpty puede aplicarse a objetos de
tipo String, List, Set, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 99


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga entre clases y subclases

¿Cuantos “metodoX” hay en ClaseHija?

public class ClasePadre {


public void metodoX (int i, int j) {
System.out.println("Enteros " + i + " y " + j);
}
// ...
}

public class ClaseHija extends ClasePadre {


public void metodoX (String c) {
System.out.println("Cadena " + c);
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 100


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrecarga entre clases y subclases


¿Cuál es el resultado de este código?

public class ClasePadre {


public int metodoX(int i, int j) {
return i + j;
}
}

class ClaseHija extends ClasePadre {


public int metodoX(int i, int j) {
return i * j;
}

public static void main(String[] args) {


ClaseHija ch = new ClaseHija();
System.out.println(ch.metodoX(5, 2)); // 7, 10, no compila?
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 101


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrescritura
Sobrescritura (overriding)
Situación que ocurre cuando una clase hija le da un implementación mas
especı́fica a un método implementado y heredado de una clase padre.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 102


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrescritura y sobrecarga

La sobrescritura en un primer momento puede parecer una


sobrecarga entre clases (mismo método con mismo número de
parámetros en dos clases distintas).
Pero al haber una relación de herencia entre las dos clases
involucradas el método de la subclase sobrescribe al método de
la superclase.
La implementación más especı́fica es preferida sobre la
implementacion de la clase padre al estar mas adaptada al objeto
actual.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 103


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrescritura

Dog le da una implementación más especı́fica a display()

class Animal {
public void display() {
System.out.println("I am an animal");
}
}

class Dog extends Animal {


public void display() {
System.out.println("I am a dog");
}
}

class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.display(); // I am a dog
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 104


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Sobrescritura de refinamiento
Sobrescritura de refinamiento: Los métodos de la superclase son
accedidos desde la subclase usando la palabra clave super
super serı́a un puntero a la superclase (de la misma forma que
this es un puntero a la clase actual).

Dog implementa display() usando super

class Dog extends Animal {


public void display() {
super.display(); // call to superclass
System.out.println("I am a dog");
}
}
class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.display(); // I am an animal .. I am a dog
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 105


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Variaciones en la sobrescritura

Ampliación de la visibilidad: El método de la subclase puede


cambiar la visibilidad pero sólo a una más permisiva (private ⇒
[package] ⇒ protected ⇒ public).

display() es protected en Animal pero public en Dog

class Animal {
protected void display() { // protected
System.out.println("I am an animal");
}
}

class Dog extends Animal {


public void display() { // public
System.out.println("I am a dog");
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 106


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Variaciones en la sobrescritura

Covarianza de tipos de retorno: El método sobrescrito puede


devolver una subclase del tipo original devuelto.

create() devuelve un Animal en la superclase y un Dog en la


subclase
class Animal {
public Animal create() { // Returns an Animal
return new Animal();
}
}

class Dog extends Animal {


public Dog create() { // Returns a Dog
return new Dog();
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 107


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Anotación @Override
¿Es esta sobrescritura de equals correcta?

public class Caja {


private int valor;
public void setValor(int v) { valor = v; }
public int getValor() { return valor; }

public boolean equals(Caja caja) {


if (caja == null) { return false; }
if (this.valor != caja.valor) { return false; }
return true;
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 108


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Anotación @Override

En Java, al contrario que en otros lenguajes, no es necesario indicar


explı́citamente que se está haciendo una sobrescritura, simplemente
con reproducir la firma del método en una subclase es suficiente.
Problema
Cualquier fallo en la escritura del método de la subclase puede
invalidar la sobreescritura (el nombre del método se deletrea mal, el
tipo u orden de los parámetros es incorrecto, etc.).
El compilador aceptará el código y el problema pasará inadvertido y
puede que sea difı́cil de detectar.
Solución
La anotación @Override situada antes de la sobrescritura de un
método fuerza al compilador a fallar si la sobrescritura no es correcta.
Es una anotación opcional pero se recomienda su uso.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 109


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Anotación @Override

Uso de @Override para detectar sobrescrituras incorrectas

public class Caja {


int valor;
public void setValor(int v) { valor = v; } Error de
public int getValor() { return valor; } compilación

@Override
public boolean equals(Caja caja) {
if (caja == null) { return false; }
if (this.valor != caja.valor) { return false; }
return true;
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 110


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Coacción
Coacción (o Coerción)
Operación semántica por la cual se convierte un argumento al tipo
esperado por una función para evitar que se produzca un error de tipos.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 111


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Coacción

Ejemplo: una función que acepta parámetros double aceptará sin


problemas parámetros int.

public class Coaccion {


public static double multiplicaPorDos(double i) {
return i*2;
}

public static void main(String[] args) {


System.out.println(Coaccion.multiplicaPorDos(5.5)); // Imprime 11.0
System.out.println(Coaccion.multiplicaPorDos(5.0)); // Imprime 10.0

// Coaccion del int 5 al double 5.0


System.out.println(Coaccion.multiplicaPorDos(5)); // Imprime 10.0
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 112


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Coacción

Las coacciones son conversiones de tipos implı́citas.


Los lenguajes incluyen reglas que indican qué tipos pueden
convertirse en otros y en qué condiciones.
La conversión de un tipo más pequeño a un tipo más grande se
denomina ensanchamiento (widening) y generalmente no conlleva
pérdida de información1 .
La conversión entre un tipo más grande a uno más pequeño se
denomina estrechamiento (narrowing) y puede implicar pérdida de
información, por lo que son necesarios type casts explı́citos.
Existe un mecanismo más avanzado de coacción denominado
Autoboxing que veremos en el siguiente capı́tulo sobre
Polimorfismo de Inclusión.

1 En Java puede ocurrir si convertimos de un número entero grande (int o long)


a un número flotante (float o double).
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 113
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Coacción
Reglas de ensanchamiento (widening) y estrechamiento
(narrowing) de tipos primitivos en Java.2

2 Las conversiones a o desde valores boolean es considerada inválida.


E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 114
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Polimorfismo de inclusión
Polimorfismo de inclusión (o polimorfismo de subtipos)
Polimorfismo que ocurre a través de las relaciones de herencia y mediante
el cual una instancia de una subclase es también un instancia de sus
superclases. Es el polimorfismo tı́pico de la POO.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 115


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Polimorfismo de inclusión
El polimorfismo de inclusión permite que un objeto de una subclase
puede utilizarse en aquellos lugares en los que se requiere un objeto
de alguna de sus superclases (una asignación de variables, un paso
de parámetros, etc.).
¡Ojo! Lo contrario no es cierto, no podemos asignar un objeto de
una superclase a una variable de las subclases.

Ejemplo: Perro y Gato son subclases de Animal

public static void metodo(Animal a) { ... }


// ...
Animal a1 = new Perro(); // Podemos asignar un Perro a un Animal
Animal a2 = new Gato(); // Podemos asignar un Gato a un Animal
Perro p1 = new Perro();
metodo(p1); // Podemos pasar por parámetro un Perro si se pide un Animal
// ...
Perro p2 = new Animal(); // Error de compilación un Animal no es un Perro

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 116


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Polimorfismo de inclusión
¿Cuál es el resultado de la ejecución de este código?

class Polimorfismo {
public static void main(String[] args) {
Perro p = new Perro(); // Perro hereda de Animal
if (p instanceof Perro) System.out.println("p es Perro");
if (p instanceof Animal) System.out.println("p es Animal");

Animal a = new Perro();


if (a instanceof Perro) System.out.println("a es Perro");
if (a instanceof Animal) System.out.println("a es Animal");
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 117


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Métodos genéricos

En muchos lenguajes OO (como Java) existe una superclase común


para todas las clases (en este caso Object).
Es sencillo crear métodos genéricos que acepten parámetros de
cualquier tipo o que devuelvan valores de cualquier tipo usando
parámetros o tipos de retorno Object.

Ejemplo: método genérico

public Object metodo(Object obj) {


// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 118


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones genéricas
Colección genérica de objetos: ArrayList (versión simplificada)

public class ArrayList {


private Object[] elementData; // Almacén de datos genéricos (Object)
private int size=0; // Tamaño
public ArrayList() {
datos = new Object[10]; // Capacidad inicial de 10
}
public boolean add(Object o) {
elementData[size++]=o; // Habrı́a que comprobar que no se
return true; // acaba el array
}
public Object get(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException();
return elementData[index];
}
public boolean isEmpty() {
return size == 0;
}
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 119


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones genéricas

Es fácil usar la clase ArrayList para hacer colecciones de perros o


colecciones de gatos.

Uso de la colección genérica

// ...
ArrayList perros = new ArrayList();
perros.add(new Perro("Milu"));
perros.add(new Perro("Snoopy"));

ArrayList gatos = new ArrayList();


gatos.add(new Gato("Garfield"));
gatos.add(new Gato("Isidoro"));
// ...

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 120


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones genéricas

Problemas del polimorfismo de inclusión y las colecciones


genéricas
1 No podemos hacer colecciones de tipos primitivos.
2 Los objetos pierden su identidad al entrar en la colección.
3 No podemos hacer colecciones de tipos seguras.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 121


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones genéricas
1 No podemos hacer colecciones de tipos primitivos
Por motivos de eficiencia los tipos primitivos de Java (int, float,
etc.) no son objetos.
Las colecciones basadas en el polimorfismo de inclusión pueden
almacenar cualquier subclase de Object, pero no pueden almacenar
tipos primitivos.

clases envoltorio (Wrapper classes)


Clases que “envuelven” a un tipo primitivo y le proveen del interfaz de
objeto que le hace falta para poder ir en una colección de objetos.

Son clases inmutables, que tienen un atributo privado del tipo


primitivo que están conteniendo y métodos de lectura del mismo.
Adicionalmente también incluyen métodos de utilidad (conversión
desde un String, constantes, etc.).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 122


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio

Tipo primitivo Clase envoltorio


byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 123


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio
Clase envoltorio Integer (version simplificada)

public final class Integer extends Number {


private final int value; // Valor interno almacenado
public Integer(int value) { this.value = value; } // Constructor
public int intValue() { return value; } // Metodo de lectura

// Constantes de utilidad
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;

// Métodos de utilidad
// Valor convertido a double
public double doubleValue() { return (double)value; }
// Valor convertido a String
public String toString() { return toString(value); }
public static String toString(int i) {
// Método estatico para convertir cualquier int a String
}
//...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 124


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio
Boxing
Proceso de introducir un tipo primitivo en su correspondiente clase
envoltorio.

Unboxing
Proceso de extraer un tipo primitivo de su correspondiente clase
envoltorio.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 125


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio
Problema de las clases envoltorio: su utilización se hace muy
engorrosa.

Ejemplo
Convertimos el ob-
// ArrayList es una coleccion jeto a Integer pa-
// implementada como un array de objetos
ArrayList l = new ArrayList();
ra insertarlo en la lista

l.add(new Integer(1));
l.add(new Integer(2)); Lo sacamos de la lista y lo
l.add(new Integer(3)); volvemos a convertir en int
Integer i = (Integer)l.get(0);
System.out.printf("El valor de 0 es %d", i.intValue());
// ...

Solución: autoboxing/autounboxing
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 126
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio
Importante: Desde Java 9 el constructor de Integer esta deprecated.
Se recomienda usar el método estático Integer valueOf(int).
Al almacenar en caché valores enteros solicitados frecuentemente
(como mı́nimo los del rango -128 a 127), tiene un rendimiento de
tiempo y espacio significativamente mejor.
Ejemplo

public final class Integer extends Number {


public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
} // ...
} IntegerCache es una caché de
// Ejemplo Integer preparada por la JVM.
ArrayList l = new ArrayList();
l.add(Integer.valueOf(1));
l.add(Integer.valueOf(2));
No crea nuevos obje-
l.add(Integer.valueOf(3));
tos, usa los de la caché.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 127


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio

Autoboxing
Proceso mediante el cual un tipo primitivo es convertido
automáticamente en su clase envoltorio cuando se requiere que se
comporte como un objeto.

Autounboxing
Proceso mediante el cual un objeto de una clase envoltorio es convertido
automáticamente en su tipo primitivo cuando se requiere que se
comporte como dicho tipo primitivo.

Es una mejora que apareció en la versión 5 de Java.


Es una versión avanzada de la Coacción aplicada a tipos primitivos y
clases envoltorio.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 128


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Clases envoltorio

Ejemplo de Autoboxing/Autounboxing
Autoboxing: un int
// ... se convierte automáti-
ArrayList l = new ArrayList();
camente en Integer
l.add(1);
l.add(2);
l.add(3); Autounboxing: Un inte-
ger se convierte en un int
Integer i = (Integer)l.get(0);
System.out.printf("El valor de 0 es %d", i);
// ...

¿Por qué necesitamos una conversión explı́cita de tipos


(Integer) para sacar un objeto de la colección?

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 129


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones genéricas

2 Los objetos “pierden” su identidad al entrar en la colección


Según el polimorfismo de inclusión. . .
Todo objeto de una subclase puede ser tratado como un objeto de su
superclase, pero mientras es tratado de esta forma no puede acceder
a las caracterı́sticas concretas de la subclase.
Al entrar en una colección. . .
El objeto sigue siendo un objeto de la subclase pero está siendo
tratado como un objeto de la superclase (Object).
Al salir de la colección. . .
La colección no devuelve objetos de la subclase, sino objetos de tipo
Object.
Para poder acceder a las caracterı́sticas de la subclase es necesario
hacer una conversión explı́cita de tipos (type cast) anteponiendo el
nombre de la clase entre paréntesis.
Un type cast incorrecto generará una excepción en ejecución.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 130


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Pérdida de identidad

Ejemplo l:ArrayList

ArrayList l = new ArrayList(); Object Object Object


Perro p1 = new Perro("Snoopy");
l.add(p1);

// Error de compilación
Perro p2 = l.get(0); l.add(p1)
// error: incompatible types
// required: Perro found: Object p3:Perro

// Typecast explı́cito p1:Perro


Perro p3 = (Perro)l.get(0);
// Evita el error de compilacion
// Puede generar uno en ejecucion Animal

// Error ejecución
Gato g1 = (Gato)l.get(0); Object
// Perro cannot be cast to Gato Perro p3 =
(Perro)l.get(0);

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 131


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones genéricas
3 No podemos hacer colecciones de tipos seguras
Si las colecciones son de tipo Object quiere decir que cualquier
objeto puede ir en las mismas.
No hay nada que evite que en una colección de perros introduzcamos
un gato.
El problema viene al extraer los elementos de la colección y hacer
una conversión explı́cita a Perro.
Solución para estos dos últimos problemas ⇒ Genericidad.

Ejemplo

ArrayList perros = new ArrayList();


perros.add(new Perro("Milu")); // Correcto
perros.add(new Perro("Snoopy")); // Correcto
perros.add(new Gato("Garfield")); // Correcto !!

Perro p1 = (Perro)perros.get(0); // Correcto


Perro p2 = (Perro)perros.get(1); // Correcto
Perro p3 = (Perro)perros.get(2); // Error ejecución !!

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 132


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Polimorfismo paramétrico
Polimorfismo paramétrico (genericidad)
Consiste en que una clase tiene uno, o varios, parámetros genéricos
definidos. En la instanciación de dicha clase se especificará qué valores
concretos tienen dichos parámetros genéricos.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 133


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Polimorfismo paramétrico
Genericidad
Clases genéricas
Parámetros de tipo
Instanciando clases genéricas
Colecciones y genericidad
Colecciones genéricas
Ventajas
Bucle for-each
Tipos vinculados
Comodines
Genericidad y subclases
Covarianza
Parámetros y subclases
Comodines y Principio Get y Put
Métodos genéricos
Interfaces y genericidad
Complicaciones de la genericidad
Compatibilidad hacia atrás (Erasure)
El warning unchecked
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 134
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Clases genéricas


Recordemos la clase Caja que almacenaba enteros.

Caja sin genericidad almacenando valores int

public class Caja {


private int valor;

public void setValor (int valor) {


this.valor = valor;
}
public int getValor () {
return valor;
}
public Caja(int valor) {
this.valor = valor;
}
public static void main(String[] args) {
Caja c = new Caja(5);
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 135


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Clases genéricas


Nueva clase caja que almacena valores en punto flotante double.

Caja sin genericidad almacenando valores double

public class CajaFlotante {


private double valor;

public void setValor (double valor) {


this.valor = valor;
}
public double getValor () {
return valor;
}
public Caja(double valor) {
this.valor = valor;
}
public static void main(String[] args) {
CajaFlotante c = new CajaFlotante(5.0);
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 136


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Clases genéricas


Solución antes de la genericidad ⇒ hacer el parámetro Object

Caja genérica pero usando Object

public class CajaGenerica {


private Object valor;

public void setValor (Object valor) {


this.valor = valor;
}
public Object getValor () {
return valor;
}
public CajaGenerica(Object valor) {
this.valor = valor;
}
public static void main(String[] args) {
CajaGenerica c = new CajaGenerica(new Perro());
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 137


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Clases genéricas


Clase genérica
Clase que incluye un parámetro de tipo (T) que representa a un
objeto cualquiera cuyo tipo real será especificado a la hora de crear
instancias de dicha clase.

Caja con genericidad

public class CajaGenerica<T> {


private T valor;

public void setValor (T valor) {


this.valor = valor;
}
public T getValor () {
return valor;
}
public CajaGenerica(T valor) {
this.valor = valor;
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 138


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Clases genéricas


Hemos creado una caja que, inicialmente, puede contener cualquier
cosa pero cuando la hayamos creado con objetos de un tipo
determinado solo podrá contener objetos de dicho tipo.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 139


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Parámetros de tipo

Parámetros de tipo
Son parámetros genéricos que especifican un tipo indeterminado.
Pueden representar a cualquier tipo que no sea un tipo primitivo:
una clase, un interfaz, un array, etc.
Por convención se representan con una única letra mayúscula,
usando habitualmente T (Tipo), E (Elemento), K (Clave) o V
(Valor) o N (Número).
La clase T no se define nunca, será sustituida por el parámetro
pasado al hacer el new de la clase que contiene el parámetro T.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 140


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Instanciando clases genéricas

Instanciando clases genéricas:


Al llamar al operador new indicamos el tipo que queremos que vaya
en nuestra caja genérica.
Como vemos los tipos primitivos no están admitidos y es necesario
hacer uso de clases envoltorio y técnicas de autoboxing.

Creación de instancias de Caja con genericidad (Java 5)

public static void main(String[] args) {


CajaGenerica<Integer> c1 = new CajaGenerica<Integer>(5);
CajaGenerica<Double> c2 = new CajaGenerica<Double>(5.0);
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 141


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Instanciando clases genéricas

Operador diamante (desde Java 7)


A partir de la versión 7 de Java se usa lo que se conoce como el
operador diamante y que consiste en que la parte del new infiere de
la declaración de la variable los tipos a usar, por lo que no es
necesario especificarlos (solo se deja el diamante <>).

Creación de instancias de Caja con genericidad y el operador diamante


(Java 7)

public static void main(String[] args) {


CajaGenerica<Integer> c1 = new CajaGenerica<>(5);
CajaGenerica<Double> c2 = new CajaGenerica<>(5.0);
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 142


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad - Instanciando clases genéricas

Inferencia de tipos en variables locales (desde Java 10)


Desde Java 10 se puede usar inferencia de tipos en variables locales.
La variable se define con la palabra clave var y el compilador infiere
el tipo adecuado de la inicialización de dicha variable

Creación de instancias de Caja con genericidad e inferencia de tipos en


variables locales (Java 10)

public static void main(String[] args) {


var c1 = new CajaGenerica<Integer>(5);
var c2 = new CajaGenerica<Double>(5.0);
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 143


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad
Clase ArrayList con genericidad (versión simplificada)

public class ArrayList<E> {


private Object[] elementData;// El array se define de tipo Object
private int size=0; // porque va a ser instanciado con Object
public ArrayList() {
elementData = new Object[10]; // No puedes crear un array de E
}
public boolean add(E element) {// Sin comprobar si el array está lleno
elementData[size++]=element;
return true;
}
public E get(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException();
return (E) elementData[index];
} // Es necesario hacer un typecast al extraer del array

public boolean isEmpty() {


return size==0;
}
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 144


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad
Ahora cuando se crea la colección se especifica su tipo mediante el
parámetro genérico.
La colección se considera ahora de tipos seguros. Si intentamos
introducir un objeto de otro tipo en la colección sucederá un error de
compilación (p.ej. si introducimos un gato en una colección de
perros).

Clase ArrayList con genericidad

ArrayList<Perro> cPerros = new ArrayList<>();


cPerros.add(new Perro("Milu"));
cPerros.add(new Perro("Snoopy"));

ArrayList<Gato> cGatos = new ArrayList<>();


cGatos.add(new Gato("Garfield"));
cGatos.add(new Gato("Isidoro"));

cPerros.add(new Gato("Felix")); // Error de compilación !!

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 145


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad

Al tener la seguridad de que en una colección de perros sólo hay


perros ya no son necesarios los type-cast para convertir un Object
en la clase deseada al extraer un objeto de la colección.

Clase ArrayList con genericidad

ArrayList<Perro> cPerros = new ArrayList<>();


cPerros.add(new Perro("Milu"));
cPerros.add(new Perro("Snoopy"));

Perro p = cPerros.get(1); // No hace falta el typecast al extraer


System.out.println(p.getNombre()); // Snoopy

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 146


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad - Ventajas

Seguridad
Se realizan comprobaciones en tiempo de compilación sobre el tipo
de la colección.
Se evitan errores en tiempo de ejecución.
Claridad
Se evitan molestas conversiones de tipos al extraer un elemento de la
colección.
Comprensibilidad
Al definir la colección se especifica su tipo, por lo que resulta más
comprensible el motivo por el cuál se está creando la colección.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 147


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad - Bucle for-each

Para aumentar la claridad en el manejo de colecciones genéricas se


introdujo el bucle for-each que permite recorrer de forma sencilla
dichas colecciones.
Aunque se le denomina for-each la palabra clave usada sigue
siendo for (no se quiso añadir una nueva palabra clave en el
lenguaje).
El bucle se leerı́a: “Por cada elemento de la coleccion haz...”.

Declaración de un bucle for-each

for (Tipo elemento : coleccion) {


metodo(elemento);
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 148


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad - Bucle for-each


Los siguientes dos bucles tienen el mismo funcionamiento.
Como vemos la sintaxis del bucle for-each es más clara.
Como inconveniente podemos destacar que no existe la variable (i)
que hace de contador del bucle. Si esta variable fuera necesaria (para
calcular una posición por ejemplo) habrı́a que descartar el bucle
for-each.

Bucle for-each vs. bucle tradicional


String[] arrayString = {"Hola", "Mundo", "como", "te", "va"};

for(int i=0; i<arrayString.length; i++)


System.out.println(arrayString[i]);

for(String s : arrayString)
System.out.println(s);

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 149


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad - Bucle for-each


Las colecciones del API de Java se recorren a través de iteradores ⇒
ver Patron Iterador en el tema 6.
También se pueden recorrer con un bucle for-each lo que
simplifica mucho su sintaxis.
En realidad cualquier clase que defina un iterador (Iterator)
puede ser recorrida por un bucle for-each.

Bucle for-each vs. bucle con iteradores


String[] arrayString = {"Hola", "Mundo", "como", "te", "va"};
List<String> listaString = Arrays.asList(arrayString);

for(String s : listaString)
System.out.println(s);

for(Iterator i = listaString.iterator(); i.hasNext(); )


System.out.println(i.next());

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 150


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Colecciones y genericidad - Bucle for-each

Con las expresiones lambda de la versión 8 de Java el bucle


for-each puede reducirse todavı́a más.
Las colecciones de Java ahora incluyen un método forEach que
acepta un expresión lambda (básicamente una función) que aplicar a
cada elemento de la colección.

Bucle for-each con expresiones lambda

String[] arrayString = {"Hola", "Mundo", "como", "te", "va"};


List<String> listaString = Arrays.asList(arrayString);

listaString.forEach(n -> System.out.println(n));

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 151


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Tipos vinculados
Del parámetro T realmente solo sabemos que es un Object.
Por lo que solo podemos llamar sobre él a los métodos declarados en
Object: toString, equals, hashCode, getClass, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 152


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Tipos vinculados
Tipos vinculados (Bounded types)
Parámetros de tipo vinculados a una clase que hace de lı́mite superior. El
tipo genérico solo podrá ser instancia de cualquier subclase de la clase
lı́mite, o una instancia de la propia clase lı́mite.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 153


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Tipos vinculados

Lı́mite superior en tipos vinculados


Podemos saber algo más del parámetro T si restringimos sus posibles
valores declarando un lı́mite superior (upper bound) usando la
cláusula extends generando ası́ un tipo vinculado.
Ejemplo: T extends Number. Donde T será cualquier subclase de
Number o incluso la propia Number.
extends con sentido de relación ES UN
Es decir, vale tanto para cuando heredamos de una clase (extends)
como para cuando implementamos un interfaz (implements).
Como ya sabemos que T es al menos una instancia de la superclase,
ya podemos usar sobre el parámetro los métodos de la superclase, y
no solo los métodos definidos en Object.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 154


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Tipos vinculados
Ejemplo de tipos vinculados

public class CajaNumerica<T extends Number> {


private T valor;
public void setValor(T valor) { this.valor = valor; }
public T getValor() { return valor; }
public CajaNumerica(T valor) { this.valor = valor; }

// doubleValue e intValue son métodos de Number


double reciproco() { return 1 / valor.doubleValue(); }
double fraccion() { return valor.doubleValue() - valor.intValue(); }

public static void main(String[] args) {


// Integer y Double son subclases de Number
CajaNumerica<Integer> n1 = new CajaNumerica<>(5);
System.out.println(n1.reciproco()); // 1/5 = 0.2
System.out.println(n1.fraccion()); // 5 => 0.0

CajaNumerica<Double> n2 = new CajaNumerica<>(5.5);


System.out.println(n2.reciproco()); // 1/5.5 = 0.18181818
System.out.println(n2.fraccion()); // 5.5 => 0.5
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 155


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Comodines
A nuestra caja numérica le queremos añadir un método absEqual
que compara el valor absoluto de la caja actual con el valor absoluto
que hay dentro de la caja pasada por parámetro.
Nos encontramos con que no podemos comparar cajas de Integer
con cajas de Double.
Caja numérica con tipos vinculados

public class CajaNumerica<T extends Number> {


// ...
boolean absEqual(CajaNumerica<T> ob) {
if(Math.abs(valor.doubleValue()) == Math.abs(ob.valor.doubleValue()))
return true;
else return false;
}
public static void main(String[] args) {
CajaNumerica<Integer> n1 = new CajaNumerica<>(5);
CajaNumerica<Double> n2 = new CajaNumerica<>(5.0);
n1.absEqual(n2); // ¡¡ ERROR DE COMPILACIÓN !!
} // Pide una NumericBox de Integer
} // Obtiene una NumericBox de Double

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 156


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Comodines
Comodines (wildcards)
Un comodı́n es un tipo especial de parámetro que representa a un tipo
desconocido en la declaración de tipos genéricos.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 157


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Tipos de comodines

Comodı́n sin vı́nculo: <?>


Representa a cualquier clase
Comodı́n con vı́nculo superior: <? extends MiClase>
Representa a la clase MiClase y a cualquiera de sus subclases
Comodı́n con vı́nculo inferior: <? super MiClase>
Representa a la clase MiClase y a cualquiera de sus superclases

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 158


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Comodines

Ahora el código funciona ya que pedimos una caja numérica con


cualquier número dentro, no necesariamente un Integer.

Caja numérica con tipos vinculados y comodines

public class CajaNumerica<T extends Number> {


// ...
boolean absEqual(CajaNumerica<? extends Number> ob) { // Comodı́n
if(Math.abs(valor.doubleValue()) == Math.abs(ob.valor.doubleValue()))
return true;
else return false;
}
public static void main(String[] args) {
CajaNumerica<Integer> n1 = new CajaNumerica<>(5);
CajaNumerica<Double> n2 = new CajaNumerica<>(5.0);
n1.absEqual(n2); // ¡¡ FUNCIONA !!
} // Pide una NumericBox de cualquier cosa
} // Pasamos una NumericBox de Double

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 159


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Tipos vinculados vs. Comodines

Tipos vinculados
Un tipo vinculado puede tener múltiples vı́nculos con otras clases.
Solo podemos definir vı́nculos superiores.
Comodines
Un comodı́n solo puede tener un vı́nculo con otra clase.
Podemos definir vı́nculos superiores o inferiores.
Recomendaciones
Usar comodines en los parámetros de una función → ver Principio
Get y Put más adelante.
No usarlos como tipo de retorno de una función (para no forzar a los
clientes de nuestro código a usar comodines).
Usar los tipos vinculados en los parámetros genéricos de clases y
métodos (estos últimos los veremos más adelante).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 160


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases

Código legal en Java ¿Qué creéis que ocurre?

String[] strArr = new String[10]; objArr[0] = new String();


Object[] objArr = strArr; objArr[1] = new Perro();

Estamos asignando un array de Opciones: Error de compilación, de


String a una variable definida ejecución o funciona.
como array de Object, y Object
es una superclase de String.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 161


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Covarianza

Covarianza
Se denomina ası́ a la propiedad de los subtipos de seguir actuando como
tales en tipos más complejos (como las listas, los arrays, etc.).

Los arrays en Java son covariantes.


En las colecciones antiguas de Java no existı́a esa discusión ya que
todas las colecciones eran del mismo tipo: Object.
¿Son las colecciones con genericidad covariantes?

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 162


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Covarianza

Código NO legal en Java ¿Qué creéis que ocurrirı́a?

List<String> strList = objList.add(new Perro());


new ArrayList<String>(); String s = strList.get(0);
List<Object> objList = strList;

Al contrario de los arrays una


List<String> no puede ser
asignada a una List<Object> ⇒
Las colecciones con genericidad son
invariantes.
Motivo: Las colecciones dejarı́an de
ser seguras (principal motivación de
la genericidad) y obtendrı́amos
errores en tiempo de ejecución.
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 163
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Parámetros y subclases


Método genérico sin usar genericidad

public static void printList(List l) {


for (Object o : l) {
System.out.println(o); // llama a o.toString();
}
} // El tipo base de todas las colecciones es Object

Método genérico usando genericidad ¿es correcto?

public static void printList(List<Object> l) {


for (Object o : l) {
System.out.println(o);
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 164


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines

Método genérico usando genericidad y comodines

public static void printList(List<?> l) {


for (Object e : l) { // Sabemos que al menos es un Object
System.out.println(e);
}
}

Uso del método genérico

List<String> strList = Arrays.asList("Hola", "Mundo", "cómo", "estas");


List<Integer> intList = Arrays.asList(5, 3, 9, 8);

printList(strList);
printList(intList);

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 165


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines

En el ejemplo anterior sólo sabı́amos de los elementos de la colección


que, al menos, deberı́an ser un Object.
Eso nos da muy poca libertad a lo que podemos hacer con ellos:
pasarlos por parámetro, devolverlos o llamar a los métodos definidos
en Object como equals, hashCode, toString, etc.
Aunque pasemos una lista de String dentro del método
printListn no podremos llamar a los métodos tı́picos de
String (charAt(), toUpperCase(), etc.) sobre los objetos de
la colección ⇒ Veremos el motivo de esto en el siguiente apartado
(Tipificación).
Esto plantea limitaciones importantes en el uso de los comodines.
De ahı́ la existencia de los comodines extends y super.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 166


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines


Recordemos la clase Figura con los métodos area() y
perimetro() y las subclases Circulo y Rectangulo.
Nos piden hacer un método que, dada una lista de figuras las recorra
sumando sus áreas y devolviendo el resultado final.

¿Es correcta esta versión del método?

public static double sumaAreas(List<Figura> l) {


double suma = 0;
for (Figura f : l)
suma += f.area();
return suma;
}

Es correcta ya que hace lo que nos han pedido pero limitada. Solo
acepta listas de Figura y no listas de alguna subclase (Circulo o
Rectangulo).
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 167
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines

Tal y como está definido sumaAreas es un método limitado

Circulo c1 = new Circulo(5);


Circulo c2 = new Circulo(3);
Rectangulo r1 = new Rectangulo(5,6);

List<Figura> figList = Arrays.asList(c1, c2, r1);


List<Circulo> cirList = Arrays.asList(c1, c2);

System.out.println("La suma es = " + sumaAreas(figList));


System.out.println("La suma es = " + sumaAreas(cirList)); // ¡¡
ERROR !!

Error de compilación en la última lı́nea, no podemos pasar un


List<Circulo> allı́ donde nos piden un List<Figure>.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 168


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines


El comodı́n extends nos permite hacer justo lo que queremos:
definir un método que sume el área de una lista definida como una
lista de figuras o una lista de cualquiera de sus subclases.

Comodı́n extends
public static double sumaAreas(List<? extends Figura> l) {
double suma = 0;
for (Figura f : l)
suma += f.area(); // => Ver Ligadura Dinámica
return suma;
}
//...
List<Figura> figList = Arrays.asList(c1, c2, r1);
List<Circulo> cirList = Arrays.asList(c1, c2);

System.out.println("La suma es = " + sumaAreas(figList));


System.out.println("La suma es = " + sumaAreas(cirList));

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 169


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines


Los comodines también tienen sus limitaciones.
Nos piden hacer un método que dada una lista de figuras o una lista
de cualquiera de sus subclases podamos incluir un Rectangulo en
ellas.

¿Es válido este código?

public static void insertaRectangulo(List<? extends Figura> l) {


l.add(new Rectangulo());
}

NO: No podemos añadir un Rectangulo a una lista de un tipo de


figuras que desconocemos.
Si fuera una lista de Circulo estarı́amos corrompiendo la lista ⇒
Las colecciones deberı́an ser seguras.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 170


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines

Conclusión
El comodı́n <?> y el comodı́n <? extends MiClase> tratan a las
colecciones como si fueran de sólo lectura.

En el primer caso sabemos que la colección es de tipo Object o de


alguna de sus subclases.
En el segundo caso sabemos que la colección es de tipo MiClase o
de alguna de sus subclases.
Insertar un elemento en cualquiera de las colecciones puede significar
corromper dicha colección (insertar un Rectangulo en una
colección de Circulo).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 171


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - Comodines

Si nos piden hacer un método que dada una lista de figuras o una
lista de cualquiera de sus superclases podamos incluir un
Rectangulo en ellas.

¿Es válido este código?

public static void insertaRectangulo(List<? super Figura> l) {


l.add(new Rectangulo());
}

SI: Si es una lista de figuras no hay problema en insertar un


Rectangulo. Si es una lista de una superclase (como Object)
tampoco serı́a un problema insertar un Rectangulo.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 172


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Genericidad y subclases - El Principio Get y Put

Principio Get y Put (también llamado Productor-Consumidor)


Utiliza el comodı́n extends cuando sólo quieras leer valores de una
colección.
Utiliza el comodı́n super cuando sólo quieras escribir valores en
una colección.
No utilices comodines cuando quieras leer y escribir al mismo tiempo
valores en una colección.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 173


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Métodos genéricos

Imaginemos que nos piden una función estática que copie los
contenidos de una lista en otra.
La versión sin genericidad funciona sin problemas porque las dos son
listas de Object.

Versión sin genericidad (clase Collections)

public static void copy(List dest, List src)

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 174


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Métodos genéricos

Alternativa con comodines sin vı́nculos ¿es válida?

public static void copy(List<?> dest, List<?> src)

No funcionarı́a ya que dest, al tener el comodı́n <?>, es de sólo


lectura.
Necesitamos poder indicar que el tipo en el origen y en el destino es
el mismo, pero puede ser cualquiera.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 175


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Métodos genéricos
Métodos genéricos
Métodos que, de forma análoga a las clases, están parametrizados por un
parámetro de tipo situado antes del tipo de retorno.

Alternativa con métodos genéricos

public static <T> void copy(List<T> dest, List<T> src)

Los parametros de tipo “presentan” al método un parámetro que


será usado en su declaración.
En el ejemplo indicamos al método que T es un parámetro genérico
y que tiene que ser el tipo de ambas listas.
Esta solución es correcta pero limitada. Solo copia, por ejemplo, una
lista de Perro sobre otra lista de Perro.
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 176
Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Métodos genéricos

Alternativa con métodos genéricos y comodines con vı́nculos

public static <T> void copy(List<? super T> dest, List<? extends T> src)

Usamos el Principio Get y Put para flexibilizar la aplicabilidad del


método.
De la lista src sólo leemos ası́ que usaremos el comodı́n extends.
En la lista dest sólo escribimos, ası́ que usamos el comodı́n super.
Ahora podremos copiar una lista de Chihuahua, subclase de
Perro, en una lista de Animal, superclase de Perro.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 177


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Métodos genéricos

Alternativa con métodos genéricos y comodines con vı́nculos

class Animal { /* ... */ }


class Perro extends Animal { /* ... */ }
class Chihuahua extends Perro { /* ... */ }

public class Copy {


public static void main(String[] args) {
ArrayList<Animal> animales = // ...
ArrayList<Perro> perros = // ...
ArrayList<Chihuahua> chihuahuas = // ...

Collections.copy(animales, chihuahuas); // ¡¡ FUNCIONA !!


}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 178


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Interfaces y genericidad

También es posible definir interfaces genéricos de la misma forma


que las clases, incluyendo un parámetro de tipo que puede luego ser
usado en sus métodos.
Muchos de los interfaces del API de Java se han generificado. Por
ejemplo Iterator.

Versión sin genericidad Versión con genericidad

public interface Iterator { public interface Iterator<E> {


boolean hasNext(); boolean hasNext();
Object next(); E next();
void remove(); void remove();
} }

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 179


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Interfaces y genericidad

Podemos implementar un interfaz en su forma genérica si la clase


que lo implementa también es genérica.

Clases genéricas e interfaces genéricos

class MiIteradorGenerico<E> implements Iterator<E> {


public boolean hasNext() { /* ... */ }
public E next() { /* ... */ }
public void remove() { /* ... */ }
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 180


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Interfaces y genericidad

Si la clase que implementa el interfaz genérico no es genérica, puede


implementar el interfaz, pero usando un tipo concreto y no un tipo
genérico.

Clases NO genéricas e interfaces genéricos

class MiIteradorInteger implements Iterator<Integer> {


public boolean hasNext() { /* ... */ }
public Integer next() { /* ... */ }
public void remove() { /* ... */ }
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 181


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Interfaces y genericidad

Método sort de la clase Collections


public static <T extends Comparable<? super T>> void sort(List<T> list)

sort permite ordenar elementos T siempre y cuando estos


elementos implementen el interfaz Comparable sobre elementos de
T o de alguna de sus superclases.
Puedo ordenar una lista de Perro si esta clase implementa
Comparable sobre perros o sobre una superclase como Animal.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 182


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Interfaces y genericidad
Hay que tener cuidado con las herramientas de autocompletado de
interfaces de los IDEs.
Si implementamos un interfaz sin genericidad...

...el IDE entenderá que queremos usar la versión sin genericidad del
mismo.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 183


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Interfaces y genericidad

Si implementamos un interfaz usando genericidad...

...el IDE entenderá que queremos usar la versión con genericidad del
mismo.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 184


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones con la genericidad

1 Código que antes era sencillo (e inseguro) ahora es más


complejo (y seguro).

Ejemplo

// Java 4: Lanza excepciones si los objetos de la lista no son comparables


public static void sort(List list)

// Java 5 en adelante: No compila si los objetos no son comparables


public static <T extends Comparable<? super T>> void sort(List<T> list)

2 ¿Cómo mantenemos la compatibilidad hacia atrás?


Código escrito para colecciones sin genericidad tiene que seguir
funcionando ahora que las colecciones están generificadas.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 185


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - Compatibilidad hacia atrás


1 Rompemos la compatibilidad hacia atrás.
El código escrito para la versión 4 de Java no serı́a válido para la
versión 5 a no se que se actualice.
Algo análogo a lo que ocurrió con Python entre las versiones 2 y 3
pero poco aceptable para un lenguaje tan extendido como Java.
2 Tenemos dos versiones del API coexistiendo.
Una con genericidad y otra sin genericidad (similar a C#).
El código antiguo puede usar la versión antigua del API y el nuevo la
nueva, pero se duplica el API y se complica la interoperabilidad entre
ambos: problemas de versiones, el nuevo código no funciona en
plataformas antiguas, etc.
3 La genericidad solo existe a nivel de compilación.
Es la solución adoptada por Java.
Se conoce como type erasure, toda la información acerca de la
genericidad no se propaga a los bytecodes.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 186


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - Compatibilidad hacia atrás

La genericidad funciona sólo en tiempo de compilación pero no en


tiempo de ejecución.

Proceso de Erasure
System.out.println("runtime type of ArrayList<String>: " +
new ArrayList<String>().getClass());
System.out.println("runtime type of ArrayList<Long> : " +
new ArrayList<Long>().getClass());

//prints: runtime type of ArrayList<String> : class java.util. ArrayList


// runtime type of ArrayList<Long> : class java.util. ArrayList

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 187


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - Compatibilidad hacia atrás

Motivación del erasure


Compatibilidad: el bytecode no generificado no se diferencia del que
si lo está. El código antiguo funciona en las nuevas JVMs y el codigo
compilado con las nuevas versiones funciona en JVMs antiguas.
Evolución, no revolución: podemos generificar un API (como el de
colecciones ) y no actualizar los clientes que lo usan.
Inconvenientes del erasure
Podemos usar un API mezclando el uso de genericidad con el no uso
de la misma ⇒ código confuso y aparición del warning unchecked
Problemas menores que surgen de no existir los genéricos en tiempo
de ejecución:
No es posible sobrecargar métodos parametrizados: List<Integer>
y List<String> son ambos List en ejecución.
Podemos romper la seguridad de los tipos en una colección con
genericidad usando funciones RTTI (Run Time Type Information) de
forma maliciosa.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 188


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - El warning unchecked

Este warning lo emite el compilador cuando estamos usando una


colección que usa genericidad sin emplear la genericidad.
El compilador permite que el código se ejecute (puede ser un código
antiguo que funcionaba con la librerı́a antes de que se generificara).
Pero emite un warning ya que puede ser un error y que nos hayamos
olvidado de usar genericidad.
Si estamos usando las colecciones con genericidad el warning no
deberia saltar nunca.

Ejemplos

List<Animal> aniList = new ArrayList(); // warning unchecked


List aniList2 = new ArrayList<Animal>(); // Al definirlo no lo emite
aniList2.add(new Gato("Garfield")); // Pero si al intentar insertar

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 189


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - El warning unchecked


Los warnings unchecked se resaltan en amarillo en el código y
también a través de un mensaje genérico en la ventana de Messages.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 190


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - El warning unchecked


En Settings... - Java Compiler podemos añadir la opción
-Xlint:unchecked como indica...

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 191


Abstracción y Encapsulamiento Tipos de Polimorfismo
Modularidad Sobrecarga
Jerarquı́a Coacción
Polimorfismo Polimorfismo de Inclusión
Tipificación Polimorfismo Paramétrico
Ligadura Dinámica

Complicaciones - El warning unchecked


...y al compilar el mensaje ya tiene información detallada de dónde
está saltando el warning unchecked.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 192


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento

2 Modularidad

3 Jerarquı́a

4 Polimorfismo

5 Tipificación
Modos de Tipificación
Restricciones del Tipado en Java
Tipado del Pato (Duck Typing)

6 Ligadura Dinámica
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 193
Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipificación

Tipos
Un tipo es una caracterización precisa de las propiedades estructurales y
de comportamiento que comparten una serie de entidades.

En los lenguajes OO un tipo se asocia con una clase pero no siempre


es ası́:
Hay tipos que no son clases (los tipos primitivos como int, float,
etc.).
En ocasiones distintas clases implementan el mismo tipo de datos (el
tipo List es implementado por dos clases distintas ArrayList y
LinkedList).
Puede ocurrir que una subclase no sea un subtipo ⇒ ver T5 -
Principios SOLID : Principio de Sustitución de Liskov.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 194


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipificación

Objetivo principal: Noción de


congruencia
La concatenación de cadenas
devuelve una cadena, contar los
caracteres de una cadena devuelve un
entero, etc.
Permiten detectar errores en un
programa y facilitan el
funcionamiento interno de los
compiladores.
Dimensiones
Estático o dinámico.
Fuerte o débil.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 195


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado estático o dinámico


Se refiere al momento
en el que se realiza la
comprobación de
tipos.

Tipado estático
La comprobación de tipos
se hace en tiempo de
compilación.

Tipado dinámico
La comprobación de tipos
se hace en tiempo de
ejecución.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 196


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado estático o dinámico

Tipado estático Tipado dinámico


Ventajas: Mejor rendimiento, Ventajas: Código más sucinto,
más legibilidad del código y los más fácil de escribir y aprender.
errores se detectan antes y más Inconvenientes: Los errores
fácilmente. tardan más en detectarse y es
Inconvenientes: el código es más más complejo solucionarlos.
rı́gido y verboso. Ejemplos: Python, JavaScript,
Ejemplos: C, Java, C#, C++. PHP, Ruby.

Java Python
String s = "Hello, World"; s = "Hello, World"

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 197


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado fuerte o débil

Se refiere a lo permisivo que es el


lenguaje a la hora de analizar las
expresiones de tipos y hacer
conversiones implı́citas entre ellos.
No es un valor binario sino una
escala.

Tipado fuerte
Las reglas de tipos son estrictas.

Tipado débil
Las reglas de tipos son más flexibles.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 198


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado fuerte o débil

Tipado débil
Tipado fuerte
Ventajas: Hay menos
Ventajas: Se detectan más
restricciones a la hora de escribir
fácilmente los errores.
el código.
Inconvenientes: Ciertas
Inconvenientes: Código más
operaciones no podrán realizarse
frágil y de resultados más
al considerarse erróneas.
impredecibles.
Ejemplos: Java, Python.
Ejemplos: C, JavaScript.
Java
JavaScript
int a = 4 + ’7’; // 59 (7 is 55 in ASCII)
int b = 4 * "7"; // compilation error 4 + ’7’; // ’47’
int c = 2 + true; // compilation error 4 * ’7’; // 28
int d = false - 3; // compilation error 2 + true; // 3
false - 3; // -3

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 199


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Dimensiones de tipado
Las dos dimensiones son independientes.

Estático y fuerte: Java. Dinámico y fuerte: Python.


Estático y débil: C. Dinámico y débil: JavaScript.
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 200
Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Restricciones del Tipado en Java


(1) Restricción de la declaración
Todas las entidades del lenguaje (variables, objetos, atributos,
parámetros) deben tener un tipo declarado.

Existen ocasiones en las que no es necesario declarar los tipos, que


son inferidos por el compilador.
Tipos inferidos

// El tipo paramétrico del ArrayList se obtiene de la declaracion de List


List<String> listaString = new ArrayList<>();

// Expresion Lambda de Java 8. El tipo de "n" no se pone explicitamente,


// pero el compilador infiere que es el tipo de la lista => String
listaString.forEach(n -> System.out.println(n));

// Inferencia de tipos en variables locales (desde Java 10)


var isValid = true;
if (isValid) System.out.println("valid");

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 201


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Restricciones del Tipado en Java

(2) Restricción de compatibilidad


En cada asignación foo = bar, y en cada llamada a una rutina en que
se usa bar como argumento real para el argumento formal foo, el tipo
de la fuente bar debe ser compatible con el tipo de destino foo.

La definición de compatibilidad en lenguajes orientados a objetos se


basa fundamentalmente en la herencia y en el polimorfismo de
inclusión: bar es compatible con foo si es descendiente de foo.

Compatibilidad a través de la herencia

// Perro es compatible con Animal porque es una de sus subclases


Animal a = new Perro();

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 202


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Restricciones del Tipado en Java


(3) Restricción de llamada a la caracterı́stica
Para poder llamar a una caracterı́stica (atributo o un método) foo desde
la clase bar, foo tiene que estar definida en bar o en uno de sus
antecesores.

¿Cuál es el resultado de la ejecución del siguiente código?

class Animal { /* El metodo "ladra" no está definido en Animal */ }


class Perro extends Animal {
public void ladra() { System.out.println("Guau"); }
public static void main(String[] args) {
Animal unAnimal = new Perro();
unAnimal.ladra();
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 203


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado del Pato (Duck Typing)

Duck Test o “prueba del pato”


(James Whitcomb Riley, escritor)
Cuando veo un pájaro que ca-
mina como un pato, nada como
un pato y grazna como un pato,
yo llamo a ese pájaro un pato.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 204


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado del Pato (Duck Typing)

Tipado del Pato (Duck Typing)


La comprobación de tipos se encarga de
comprobar que el objeto en cuestión
tiene los aspectos deseados (camina,
nada, grazna) y no de qué tipo de objeto
se trata.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 205


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado del Pato (Duck Typing)


El duck typing es tı́pico de los lenguajes con tipado dinámico.
Duck typing en Python

class Duck:
def quack(self):
print("Quack, quack!")
def fly(self):
print("Flap, Flap!")

class Person:
def quack(self):
print("I’m Quackin’!")
def fly(self):
print("I’m Flyin’!")

def in_the_forest(mallard): # mallard no tiene ningún tipo declarado


mallard.quack()
mallard.fly()

in_the_forest(Duck()) # Imprime "Quack, quack! Flap, Flap!"


in_the_forest(Person()) # Imprime "I’m Quackin’! I’m Flyin’!"

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 206


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado del Pato (Duck Typing)


Al ser un lenguaje con tipado estático Java no admite el duck
typing.

Duck typing en Java

class Duck {
Incumple restricción (2)
public void quack() {
System.out.println("Quack, quack!"); class DuckTyping {
} // la función tiene un tipo declarado
public void fly() { public static void in_the_forest
System.out.println("Flap, Flap!"); (Duck mallard) {
} mallard.quack();
} mallard.fly();
}
class Person {
public void quack() { public static void main(String[] args){
System.out.println("I’m Quackin’!"); in_the_forest(new Duck());
} in_the_forest(new Person()); // ERROR
public void fly() { // Person no es compatible con Duck
System.out.println("I’m Flyin’!"); }
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 207


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Tipado del Pato (Duck Typing)


Al ser un lenguaje con tipado estático Java no admite el duck
typing.

Duck typing en Java


Incumplen restricción (3)
class Duck {
public void quack() {
System.out.println("Quack, quack!"); class DuckTyping {
} // Ponemos de tipo la superclase
public void fly() { public static void in_the_forest
System.out.println("Flap, Flap!"); (Object mallard) {
} mallard.quack(); // ERROR
} mallard.fly(); // ERROR
// quack() y fly() no están definidos
class Person { // en Object
public void quack() { }
System.out.println("I’m Quackin’!");
} public static void main(String[] args){
public void fly() { in_the_forest(new Duck());
System.out.println("I’m Flyin’!"); in_the_forest(new Person());
} }
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 208


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

Por qué Java no admite el tipado del pato (duck typing)

Existen ciertas operaciones con los tipos que pueden ser válidas,
pero si no hay una seguridad absoluta de que lo son entonces es
mejor no permitirlas.
La idea subyacente es que es mejor detectar los posibles errores en
tiempo de compilación y no en tiempo de ejecución (ya que son una
mayor molestia tanto para usuarios como para desarrolladores).
Ejemplo
Duck y Person tienen definidos los métodos quack() y fly()
por lo que podrı́an sin problemas ser pasados por parámetro a la
función in the forest(Object mallard).
Pero la función admite objetos de todo tipo, no todos los objetos
tienen los métodos quack() y fly(), por lo que la función falları́a
en tiempo de ejecución cada vez que pasaramos uno de estos objetos.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 209


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

¿Cómo solucionar el duck typing en Java?

(1) Usando conversiones de tipos


explı́citas ⇒ problemas en ejecución

class Duck {
public void quack() { class DuckTyping {
System.out.println("Quack, quack!"); public static void in_the_forest
} (Object mallard) {
public void fly() { ((Duck)mallard).quack();
System.out.println("Flap, Flap!"); ((Duck)mallard).fly();
} }
}
public static void main(String[] args){
class Person { in_the_forest(new Duck()); // OK
public void quack() { in_the_forest(new Person()); // ERROR
System.out.println("I’m Quackin’!"); }
}
public void fly() {
System.out.println("I’m Flyin’!"); Pueden dar lugar a
} errores en ejecución
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 210


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

¿Cómo solucionar el duck typing en Java?

(2) Usando instanceof ⇒


antipatrón

class Duck { class DuckTyping {


public void quack() { public static void in_the_forest
System.out.println("Quack, quack!"); (Object mallard) {
} if (mallard instanceof Duck) {
public void fly() { ((Duck)mallard).quack(); // OK
System.out.println("Flap, Flap!"); ((Duck)mallard).fly(); // OK
} } else if(mallard instanceof Person){
} ((Person)mallard).quack(); // OK
((Person)mallard).fly(); // OK
class Person { } else {
public void quack() { // ...
System.out.println("I’m Quackin’!"); }
} } ¡¡NO!! Preguntar por el
public void fly() { } tipo de un objeto para
System.out.println("I’m Flyin’!"); hacer una cosa u otra
}
} es un anti-patrón de la
orientación a objetos

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 211


Abstracción y Encapsulamiento
Modularidad Modos de Tipificación
Jerarquı́a Restricciones del Tipado en Java
Polimorfismo Tipado del Pato (Duck Typing)
Tipificación
Ligadura Dinámica

¿Cómo solucionar el duck typing en Java?


(3) Usar interfaces ⇒ solución más
orientada a objetos

interface QuackAndFly {
public void quack();
public void fly(); class DuckTyping {
} public static void in_the_forest
class Duck implements QuackAndFly { (QuackAndFly mallard) {
public void quack() { mallard.quack();
System.out.println("Quack, quack!"); mallard.fly();
} }
public void fly() {
System.out.println("Flap, Flap!"); public static void main(String[] args){
} in_the_forest(new Duck()); // OK
} in_the_forest(new Person()); // OK
class Person implements QuackAndFly { }
public void quack() { }
System.out.println("I’m Quackin’!");
}
public void fly() { Solución más orientada a
System.out.println("I’m Flyin’!"); objetos. Funciona gracias
} a la Ligadura Dinámica
}
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 212
Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Índice
1 Abstracción y Encapsulamiento

2 Modularidad

3 Jerarquı́a

4 Polimorfismo

5 Tipificación

6 Ligadura Dinámica
Funcionamiento
Esencia del Diseño OO
Métodos sin Ligadura Dinámica
E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 213
Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ligadura dinámica
Ligadura
Proceso que se encarga de ligar o relacionar la llamada a un método (o
mensaje) con el código que se ejecuta finalmente.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 214


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Tipos de ligadura

Ligadura estática (o temprana)


Consiste en realizar el proceso de ligadura en tiempo de compilación
según el tipo declarado del objeto al que se manda el mensaje.
La utilizan (en Java) los métodos de clase y los métodos de
instancia que son privados o finales (ya que estos últimos no pueden
ser sobrescritos).

Ligadura dinámica (o tardı́a)


Consiste en realizar el proceso de ligadura en tiempo de ejecución
siendo la forma dinámica del objeto la que determina la versión del
método a ejecutar.
Se utiliza en todos los métodos de instancia en Java que no son ni
privados ni final.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 215


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ejemplo de ligadura dinámica


Consideremos el ejemplo de la clase abstracta Figura que define
dos métodos abstractos area y perimetro. Y las clases Circulo
y Rectangulo que le dan una implementación a dichos métodos.

clase Figura
public abstract class Figura {
public abstract double area();
public abstract double perimetro();
}
public class Circulo extends Figura {
public double area() { return Math.PI*radio*radio; }
public double perimetro() { return 2*Math.PI*radio; }
// ...
}
class Rectangulo extends Figura {
public double area() { return base*altura; }
public double perimetro() { return (base*2)+(altura*2); }
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 216


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ejemplo de ligadura dinámica

Consideremos de nuevo el método sumaAreas que sumaba las


áreas de una lista de figuras.

clase Figura
public static double sumaAreas(List<? extends Figura> l) {
double suma = 0;
for (Figura f : l) {
suma += f.area();
}
La llamada a area ejecuta
return suma;
} distintos métodos según el
tipo dinámico de la figura que
estamos tomando de la lista

No existe el problema de la llamada a la caracterı́stica porque el


método area está en Figura aunque sea de forma abstracta.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 217


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ejemplo de ligadura dinámica


Creamos ahora una nueva subclase de Figura denominada
Cuadrado.

clase Cuadrado
class Cuadrado extends Figura {
private double lado;

public Cuadrado(double lado) {


this.lado = lado;
}

public double area() {


return lado * lado;
}

public double perimetro() {


return lado * 4;
}
// ...
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 218


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ejemplo de ligadura dinámica

Comprobamos como el método sumaAreas funciona perfectamente


con la clase Cuadrado y llama correctamente a su método suma.

clase Cuadrado
List<Figura> l = new ArrayList<>();
l.add(new Rectangulo(2, 3));
l.add(new Circulo(3));
l.add(new Rectangulo(5, 4));
l.add(new Cuadrado(2));

System.out.println("Suma = " + sumaAreas(l));

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 219


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Esencia del diseño OO


Esencia del diseño OO
Usar las propiedades tı́picas de la OO (herencia, polimorfismo y
ligadura dinámica) conjuntamente para obtener las ventajas que ofrece
la OO: flexibilidad, escalabilidad, extensibilidad, abstracción, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 220


Abstracción y Encapsulamiento
Modularidad
Jerarquı́a ¡¡ IMPORTANTE !!
Funcionamiento
Esencia del Diseño OO
Polimorfismo Casi todos los ejemplos
Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica de principios y patrones
de diseño que veremos
Esencia del diseño OO en los siguientes temas
serán una variación
de este ejemplo.

Propiedades:
Herencia: usada para describir la relación entre las figuras.
Polimorfismo: usado para crear una lista de distintos tipos de figuras.
Ligadura dinámica: usada al llamar al método area.
Ventajas:
Estamos creando código (sumaAreas) que será capaz de trabajar,
sin modificarlo, con código futuro que aún no está escrito
(Cuadrado) ⇒ Flexibilidad, Escalabilidad, Extensibilidad, etc.
El método sumaAreas desconoce con qué clases trabaja, lo único
que sabe es que son figuras ⇒ Abstracción, Seguridad, Facilidad
de mantenimiento, etc.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 221


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ejemplo de ligadura dinámica

¿Cuál es el resultado de este código?

abstract class Animal {


public void hazRuido() { System.out.println("No hago ruido"); }
}
class Perro extends Animal {
public void hazRuido() { ladra(); }
public void ladra() { System.out.println("Guau"); }
}
class Pez extends Animal { /* no redefine hazRuido() */ }
// ...
Animal a1 = new Perro();
Animal a2 = new Pez();
a1.hazRuido();
a2.hazRuido();
// ...

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 222


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ligadura dinámica y métodos estáticos


¿Cuál es el resultado de este código?

class Padre {
public static void metodoEstatico()
{ System.out.println("Padre");}
}
class Hijo extends Padre {
public static void metodoEstatico()
{ System.out.println("Hijo"); }
}
class Estaticos {
public static void main(String[] args) {
Padre p = new Hijo();
p.metodoEstatico();
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 223


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ligadura dinámica y métodos estáticos

Al tener ligadura estática los métodos estáticos no aprovechan todas


las posibilidades que ofrece la OO.
De todas formas hay situaciones en las que puede ser interesante
plantearse hacer un método estático:
Cuando el método no modifica el estado del objeto ni accede a sus
atributos.
Cuando queremos llamar al método sin tener que disponer de una
instancia de la clase.
Cuando el funcionamiento del método sólo depende de los
parámetros que le pasemos (ej. public int factorial(int
numero)).
Métodos de utilidad que podrı́an situarse en cualquier clase (ej.
determinar si un String es vacı́o
StringUtils.isEmpty(String text)).
Desarrollo de algunos patrones de diseño ⇒ Método Factorı́a.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 224


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ligadura dinámica y métodos finales


¿Cuál es el resultado de este código?

class Padre {
public final void metodoFinal() {
System.out.println("Padre");
}
}
class Hijo extends Padre {
public final void metodoFinal() {
System.out.println("Hijo");
}
}
class Finales {
public static void main(String[] args) {
Padre p = new Hijo();
p.metodoFinal();
}
}

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 225


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ligadura dinámica y métodos finales

Clases finales
Clases que impiden ser extendidas a través de herencia.

Métodos finales
Métodos que impiden que las subclases los sobrescriban.

Los métodos finales no tienen por qué residir en clases finales.


De hecho, los métodos de las clases finales son implı́citamente
finales ya que nunca pueden ser sobrescritos.

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 226


Abstracción y Encapsulamiento
Modularidad Funcionamiento
Jerarquı́a Esencia del Diseño OO
Polimorfismo Métodos sin Ligadura Dinámica
Tipificación
Ligadura Dinámica

Ligadura dinámica y métodos finales

Clases finales
Las clases finales limitan la posible extensibilidad del código y deben
por lo general evitarse salvo situaciones puntuales ⇒ Las clases
inmutables se definen finales para asegurarse de que las subclases no
rompen dicha inmutabilidad.
Métodos finales
Los métodos finales también limitan algo esencial en la orientación a
objetos como es la sobrescritura de métodos.
En ocasiones no queremos limitar la posibilidad de que una clases
tenga subclases, sino solo limitar la posibilidad de sobrescribir ciertos
métodos ⇒ Patrón Método-Plantilla (Tema 6).

E. Mosqueira Rey (Coordinador) Tema 3: Propiedades Básicas de la OO 227


Tema 3: Propiedades básicas de la Orientación a
Objetos
Diseño Software (614G01015)

Eduardo Mosqueira Rey (Coordinador)

Departamento de Ciencias de la Computación y Tecnologı́as de la Información


Facultad de Informática

También podría gustarte