SlideShare una empresa de Scribd logo
1 de 80
Lenguajes de Programación 2
Programación Orientada a Objetos
Herencia
Ing. Gustavo Arsenio Sosa Cataldo
FACULTAD POLITÉCNICA - UNA
• Las clases solas no son suficientes para conseguir:
• Reutilización
• Generar código que:
• Capture los aspectos comunes en grupos de estructuras
similares, y
• Permita la variación de estructuras de datos y algoritmos
subyacentes
• Extensibilidad
• Necesidad de mecanismos para lograr:
• Principio Abierto-Cerrado
• Principio de la Elección Única
Introducción
 Entre algunas clases pueden existir relaciones conceptuales:
 Generalización: Se detectan las propiedades comunes.
 Extensión: Se amplían las funcionalidades.
 Especialización: Se implementan funcionalidades que son
especificas
 Combinación: Se combinan las funcionalidades de dos o más
objetos
 ¿Tiene sentido crear una clase a partir de otra(s)?
 Herencia: soporte para registrar y utilizar estas relaciones,
que posibilita la definición de una clase a partir de
otra(s).
Introducción
Jerarquía de Clases
 La herencia permite organizar las clases en jerarquías en las
cuales se:
 Reutiliza el código de los objetos Padres.
 Extiende los tipos de objetos del sistema.
 Puede existir una clase “raíz” en la jerarquía de la cual heredan
las demás directa o indirectamente.
 La clase raíz incluye todas las características comunes a todas
las clases
 En Java esta clase es la clase Object
• boolean equals(Object o)
• String toString()
• int hashCode()
Jerarquía de Clases
Object
Number
Integer Float Double
Figura
FiguraCerrada
Polígono Círculo
Rectángulo
Herencia entre clases
 Si una clase B hereda de otra A, entonces:
 B incorpora la estructura (atributos) y comportamiento (métodos) de A,
 B puede incluir adaptaciones:
 B puede añadir nuevos atributos y métodos
 B puede redefinir métodos de A
• Refinamiento: Extendiendo el uso de un método de A
• Reemplazo: Sobrescribir la implementación de un método de A
 B puede implementar un método abstracto en A
B hereda de A (A es la superclase y B la subclase)
C hereda de B y A
B y C son subclases de A
B es un descendiente directo de A
C es un descendiente indirecto de A
Tipos de Herencia
• Herencia simple
• Una clase puede heredar de una única
clase.
• Java, C#
• Herencia múltiple
• Una clase puede heredar de varias clases.
• Clases forman un grafo dirigido acíclico
• Problemas:
• Herencia Repetida.
• Conflicto de Nombres.
A
B C
D
B C
D
Problemas de la Herencia Múltiple
• Herencia Repetida
Ocurre cuando se hereda una misma
característica de dos o más líneas de
herencia.
• Solución
1.Especificar que línea de herencia usar.
2.Herencia Parcial, se elige que heredar
de cada línea de herencia.
3.Renombrar características heredadas
B
a, b
C
a, c
D
a, b, c, d
A
a
Problemas de la Herencia Múltiple
• Conflicto de Nombres
Ocurre cuando se heredan característica
diferentes pero con mismo nombre de dos
o más líneas de herencia.
• Solución
1.Especificar que línea de herencia usar.
2.Herencia Parcial, se elige que heredar
de cada línea de herencia.
3.Renombrar características heredadas
B
b, x
C
c, x
D
b, c, x
¿Cómo detectar la herencia durante
el diseño?
• Generalización (Factorización)
Se detectan clases con un comportamiento común
(p.e. Libro y Revista son de tipos de Publicación)
• Especialización (Abstracción)
Se detecta que una clase es un caso especial de otra
(p.e. Rectángulo de Polígono)
Polígonos y Rectángulos
 Tenemos la clase Poligono y necesitamos representar
rectángulos:
 ¿Debemos crear la clase Rectángulo partiendo de cero?
 Podemos aprovechar la existencia de similitudes y
particularidades entre ambas clases
Polígono
vértices : List<Punto>
trasladar(int a, int b)
dibujar()
borrar()
perimetro()
Polígono(List<Punto> v)
Rectángulo
lado1 : int
lado2 : int
perimetro()
Rectángulo(List<Punto> v, int l1, int l2)
diagonal()
Polígonos y Rectángulos
 Un rectángulo tiene muchas de las características de un polígono
(dibujar(), borrar(), trasladar())
 Pero tiene características especiales (diagonal(), lado1, lado2)
 Algunas características de polígono pueden implementarse más
eficientemente (perímetro())
Polígono
vértices : List<Punto>
trasladar(int a, int b)
dibujar()
borrar()
perimetro()
Polígono(List<Punto> v)
Rectángulo
lado1 : int
lado2 : int
perimetro()
Rectángulo(Punto vsi, int l1, int l2)
diagonal()
import gráficos.Punto;
Import java.util.List;
public class Polígono {
//Un polígono es una lista de puntos
protected List<Punto> vértices = null;
public Polígono(List<Punto> vértices) {
this.vértices = vértices;
}
public void trasladar (double a, double b) {…}
public void dibujar() {…}
public void borrar() {…}
public double perímetro() {…}
}
Polígonos y Rectángulos
public double perímetro() {
double total = 0;
Punto ant = null;
Punto actual = vertices.get(0);
for (int i = 1; i < vertices.size(); i++){
ant = actual;
actual = vertices.get(i);
total = total + actual.distancia(ant);
}
total = total +
actual.distancia(vertices.get(0));
return total;
}
Polígonos y Rectángulos
public class Rectángulo extends Polígono {
protected double lado1, lado2; //Nuevos atributos
public Rectángulo(Punto vsi; double lado1,
double lado2) {
this.vértices = new List<Punto>;
this.vértices.add(vsi);
Punto vsd = new Punto (vsi)
vsd.trasladar (0, lado1);
this.vertices.add(vsd);
...
this.lado1 = lado1;
this.lado2 = lado2;
}
...
Polígonos y Rectángulos
public double perímetro() {
return (2*(lado1 + lado2 ));
}
public double diagonal() {
return Math.sqrt(Math.pow(lado1, 2) +
Math.pow(lado2, 2))
}
// ¿Y que pasa con los demás métodos ?
}
 Todas las demás características de Polígono están
disponibles automáticamente para la clase Rectángulo, no
es necesario que se repitan.
Polígonos y Rectángulos
Significado de la herencia
Clases Herencia
Módulo Mecanismo de Extensión Mecanismo de Reutilización
Tipo Mecanismo de Especialización Clasificador de Tipos
Sean:
• Prop(X): Conjunto de características de la clase X
• Dom(X): Conjunto de instancias de la clase X
A {Prop(A)}
B {Prop(B)}
• B Hereda de A  Prop(A)  Prop(B)
• Cualquier objeto de B puede ser
considerado un objeto de A
• Dom(B)  Dom(A)  B es un Subtipo de A
• Si se espera un objeto A, podemos recibir o
enviar un objeto B.
Significado de la herencia
Polígono
vértices : List<Punto>
trasladar(int a, int b)
dibujar()
borrar()
perimetro()
Polígono(List<Punto> v)
Rectángulo
lado1 : int
lado2 : int
perimetro()
Rectángulo(Punto vsi, int l1, int l2)
diagonal()
1. Prop(Polígono) = {vértices, trasladar(), dibujar(), borrar(), perímetro()}
2. Prop(Rectángulo) = {vértices, trasladar(), dibujar(), borrar(), perímetro(),
lado1, lado2, diagonal()}
Significado de la herencia
1. Dom(Polígono) = {recA, recB, polA, polB}
2. Dom(Rectángulo) = {recA, recB, PolB}
Rectángulo recA = new Rectángulo(…);
Polígono polA = new Polígono(…);
Polígono polB = new Rectángulo(…);
Rectángulo recB = new Rectángulo(…);
Polígono polC = null;
Rectangulo recC = null;
Significado de los subtipos
• El principio de sustitución de Liskov [B. Liskov 88]:
• “ Si para cada objeto O1 de tipo S hay un objeto O2 de tipo T, tal
que para todos los programas P definidos en términos de T, sí el
comportamiento de P no varía cuando se sustituye O2 por O1
entonces S es un subtipo de T ”
• Funciones que utilizan referencias a superclases deben ser capaces
de utilizar objetos de sus subclases sin saberlo.
• public static void dibujarEnPantalla(Polígono p);
• dibujarEnPantalla(new Rectangulo(...))
Herencia y Creación
 Los constructores no se heredan
 El constructor de la clase hija refina el comportamiento del
constructor del padre
 La primera sentencia del constructor de la clase hija SIEMPRE es
una llamada al constructor de la clase padre.
 La llamada al constructor del padre puede ser:
 Implícita:
• Si se omite, se llamará implícitamente al constructor
por defecto de la clase padre
• Equivale a poner como primera sentencia super();
 Explícita:
• super(); o super(a,b); o . . .
• Dependiendo del número y tipo de parámetros se invoca
uno de los constructores de la clase padre
Acceso protegido en Java
• Una subclase no puede acceder a los atributos o métodos privados de su
superclase
• Para permitir que un método de la subclase pueda acceder a un atributo o
un método de la superclase, éste tiene que declararse como protected o
public
• Resumen de modificadores de acceso:
– private – visible sólo en la clase
– public – visible a todas las clases
– protected – visible a las subclases y a (sub)clases del paquete
– default – visible en las clases del paquete
Herencia en Java
• Toda clase hereda directa o indirectamente de la clase Object
• public class Poligono {...} // hereda de Object
• public class Rectangulo extends Poligono {...}
• Una subclase hereda de su superclase métodos y atributos
tanto de clase como de instancia, pero solo puede acceder a las
que están definidas como public o protected.
• Una subclase puede añadir nuevos métodos y atributos.
• Una subclase puede redefinir métodos heredados.
Redefinición
• La redefinición reconcilia la Reutilización con la Extensibilidad:
• “Es raro reutilizar un componente software sin necesidad de
cambios”
• Los atributos no se pueden redefinir, sólo se OCULTAN
• El campo de la superclase todavía existe pero solo se puede
acceder por medio de super
• Un método de la subclase con la misma signatura y valor de
retorno que un método de la superclase lo está REDEFINIENDO.
• Si se cambia el tipo de los parámetros se está SOBRECARGANDO
el método original y no redefiniendo
Redefinición de métodos
• Una clase hija puede redefinir un método de la clase padre por
dos motivos:
• Reemplazo:
• Mejorar implementación.
• Ej: redefinición de perímetro() en la clase
Rectángulo.
• Cambiar la Implementación sin variar la semantica.
• Refinamiento:
• Método del padre + acciones específicas.
• La invocación al método del padre se hace usando la
palabra super
Refinamiento. Ejemplo
public class CuentaAhorro extends Cuenta {
...
public void ingresar(double cantidad) {
//Hace lo mismo que el método de la clase padre
super.ingresar(cantidad);
//Además hace cosas propias de la CuentaAhorro
beneficio = cantidad * PORCENTAJE_BENEFICIO;
}
}
¿Qué se puede cambiar en la
redefinición?
• El nivel de acceso
• Siempre que se relaje
• Puede pasar de protected a public
• Por ejemplo, método clone en Object es protected
• No se puede pasar de public a private
• El tipo de retorno
• Siempre que el tipo de retorno del método redefinido sea compatible
con el tipo de retorno del método original.
• Object  protected Object clone() … (desde Java 1.5)
• Punto  public Punto clone() …
Restringir la herencia y
redefinición
 En Java se puede aplicar el modificador final a un
método para indicar que no puede ser redefinido.
 El modificador final es aplicable a una clase
indicando que no se puede heredar de ella.
 ¿El modificador final va contra el principio abierto-
cerrado?
Polimorfismo
• El término polimorfismo significa que hay un nombre (referencia,
método o clase) y muchos significados diferentes para el mismo
(distintas definiciones).
• Formas de polimorfismo [Budd’02]:
– Polimorfismo de asignación (variables polimorfas)
– Polimorfismo puro (función polimorfa)
– Polimorfismo ad hoc (sobrecarga)
– Polimorfismo de inclusión (redefinición)
– Polimorfismo paramétrico (genericidad)
Polimorfismo de Asignación
 Capacidad de una entidad de referenciar en tiempo de ejecución
a instancias de diferentes clases
 El conjunto de clases a la que se puede hacer referencia está
restringido por la Herencia.
 Dada una referencia R de tipo T, en un lenguaje orientado a
objetos fuertemente tipado R puede referenciar a cualquier objeto
de tipo S, siempre que S sea un subtipo de T.
 Number n;
n = new Integer();
n = new Double();
n = new BigDecimal();
Tipo estático y tipo dinámico
• Tipo estático (te):
– Tipo asociado en la declaración. Ej: Number n;
• Tipo dinámico:
– Tipo correspondiente a la clase del objeto conectado a la
entidad en tiempo de ejecución. Ej: n = new Float(3.14);
• Conjunto de tipos dinámicos (ctd):
– Conjunto de posibles tipos dinámicos de una entidad
A oa; B ob; C oc;
te(oa) = A ctd(oa) = {A,B,C,D,E,F}
te(ob) = B ctd(ob) = {B, D, E}
te(oc) = C ctd(oc) = {C,F}
Entidades y rutinas polimorfas
Conexión polimorfa: el origen y el destino tiene tipos diferentes
Poligono p;
Rectangulo r;
a) asignación:
p = r;
-- p es una entidad polimorfa
(polimorfismo de asignación)
b) paso de parámetros:
void f (Poligono p)… -- f es una rutina polimorfa
(polimorfismo puro)
Polimorfismo puro vs. Sobrecarga
• Funciones sobrecargadas ≠ funciones polimórficas
• Sobrecarga:
– Dos o mas funciones comparten el nombre y distintos
argumentos (nº y tipo). El nombre es polimórfico.
– Distintas definiciones (distintos comportamientos)
– Función correcta se determina en tiempo de compilación
según la signatura.
• Funciones polimórficas:
– Una única función que puede recibir una variedad de
argumentos (comportamiento uniforme).
– La ejecución correcta se determina dinámicamente en
tiempo de ejecución.
Herencia y sistema de tipos
A a; B b; C c; D d;
¿Son válidas las siguientes asignaciones?
a = b; c = b; a = d
Ligadura dinámica ó
Enlace dinámico
{fδ}
redefine f
¿qué versión de f se
ejecuta?
A oa;
… // asignacion
de oa
oa.f(..);
Regla de la ligadura dinámica
La forma dinámica del objeto determina la versión de la operación que
se aplicará.
• La versión de un método en una clase es la introducida
por la clase (redefinición u original) o es la heredada.
• Ejemplo:
Poligono p = new Poligono();
Rectangulo r = new Rectangulo();
Double x;
x = p.perimetro() → perimetro POLIGONO
x = r.perimetro() → perimetro RECTANGULO
p = r;
x = p.perimetro() → perimetro RECTANGULO
Ligadura dinámica ó
Enlace dinámico
{fδ}
redefine f
A a;
B b = new B();
D d = new D();
a = b;
a.f(); //q versión?
a = d
a.f(); //q versión?
Ligadura dinámica ó
Enlace dinámico
Ejemplo 2:
void visualizar (Figura [] figuras){
for (Figura figura : figuras)
figura.dibujar();
}
¿Qué sucede si aparece un nuevo tipo de figura?
¿Qué relación existe entre ligadura dinámica y comprobación
estática de tipos?
Sea el mensaje x.f (), la comprobación estática de tipos garantiza que al
menos el mensaje sea válido, y la ligadura dinámica garantiza que se
ejecutará la versión más apropiada.
Ligadura dinámica ó
Enlace dinámico
Ejemplo ligadura dinámica, super y this
class Uno {
public int test(){return 1;}
public int result1(){return this.test();}
}
class Dos extends Uno{
public int test(){return 2;}
}
class Tres extends Dos{
public int result2(){return this.result1();}
public int result3(){return super.test();}
}
class Cuatro extends Tres{
public int test(){return 4;}
}
public class PruebaSuperThis{
public static void main (String args[]){
Uno ob1 = new Uno();
Dos ob2 = new Dos();
Tres ob3 = new Tres();
Cuatro ob4 = new Cuatro();
System.out.println("ob1.test = "+ ob1.test());
System.out.println("ob1.result1 = " + ob1.result1());
System.out.println("ob2.test = " + ob2.test());
System.out.println("ob2.result1 = " + ob2.result1());
System.out.println("ob3.test = " + ob3.test());
System.out.println("ob4.result1 = " + ob4.result1());
System.out.println("ob3.result2 = " + ob3.result2());
System.out.println("ob4.result2 = " + ob4.result2());
System.out.println("ob3.result3 = " + ob3.result3());
System.out.println("ob4.result3 = " + ob4.result3());
}
}
Ejemplo ligadura dinámica, super y this
1
{fδ}
redefine f
A a;
B b = new B();
D d = new D();
a = b;
a.f(); //versión B
a = d
a.f(); //versión D
Principio de la Elección Única
Principio de la Elección Única
Gracias al polimorfismo el modulo A conoce todas sus variantes por
medio del enlace dinámico se aplica la versión correcta de una operación
Código Genérico
 Un único código con diferentes interpretaciones en tiempo
de ejecución
 Es fundamental que el lenguaje soporte:
 Polimorfismo
 Ligadura Dinámica
 El mismo código ejecutará cosas distintas en función del
Tipo Dinámico de la entidad polimórfica (ligadura dinámica)
 Gracias al polimorfismo y la ligadura dinámica se satisface
el criterio de reutilización de Variación de la
Implementación.
Código Genérico
 class CalculadorDeCostos {
/* Los objetos de esta clase calculan el costo de
diversas cosas */
...
public double precioDeVallado(Parcela p) {
Poligono forma = p.getForma();
double costo = forma.getPerimetro() *
this.getCostoVallado();
return costo;
}
}
 forma puede ser cualquier objeto de tipo Poligono.
 El mensaje forma.getPerimetro() tendrá diferentes significados según
sea el tipo dinámico de forma.
Copias de Objetos
 Tipos de copia:
 Copia superficial: los campos de la copia
son exactamente iguales a los del objeto
original.
 Copia profunda: los campos primitivos de
la copia son iguales y las referencias son
copias de los objetos referenciados por el
original.
 Adaptada: adaptada a la necesidad de la
aplicación.
Copia superficial
 Alias Dinámico:
Incorrecto al
compartir las
últimas
operaciones
 No deberían
tener el mismo
valor de código
Copia profunda
 No tiene
sentido
duplicar el
objeto Persona
 No deberían
tener el mismo
código
Copia adaptada
Copia adaptada
 Para implementar la copia se debe redefinir el método:
 protected Object clone();
 class Cuenta {
...
public Cuenta clone() {
Cuenta clon = super.clone(); // copia superficial
clon.codigo = Cuenta.getSgteCodigo(); // código nuevo
clon.ultOper = new ArrayList<Integer>();
// se copian las operaciones
for (Integer oper : this.ultOper) {
clon.ultOper.add(new Integer(oper));
}
return clon;
}
}
Igualdad de Objetos
 Tipos de igualdad:
 Superficial: los campos primitivos de los dos objetos son iguales
y las referencias apuntan a los mismos objetos (==).
 Profunda: los campos primitivos son iguales y las referencias no
son los mismos objetos pero estos son iguales en profundidad
(equals).
 Adaptada: adaptada a las necesidades de la aplicación.
 ¿Cuándo dos cuentas son iguales?
Igualdad de Objetos
 Para implementar la comparación se debe redefinir el método:
 public boolean equals(Object o2);
 class Cuenta {
...
public boolean equals(Object o2) {
if(!(o2 instanceof Cuenta) ) return false;
Cuenta c2 = (Cuenta) o2;
if ( this.saldo != c2.saldo || this.titular != c2.titular ||
this.ultOper.size() != c2.ultOper.size() )
return false;
for (int i = 0; i < this.ultOper.size() ; i++) {
if (! this.ultOper.get(i).equals(
c2.ultOper.get(i)) )
return false;
}
return true;
}
}
Genericidad restringida
 Public class Vector <T> {
private int count;
public T item( int i ){…}
public void put (T v, int index){…}
public Vector<T> suma (Vector<T> otro){
Vector<T> result= new Vector<T>();
for(int i = 1; i <= count; i++) {
result.put( this.item(i) + otro.item(i) , i);
}
return result;
}
}
Genericidad restringida
 Public class Vector <T extends Number> {
private int count;
public T item( int i ){…}
public void put (T v, int index){…}
public Vector<T> suma (Vector<T> otro){
Vector<T> result = new Vector<T>();
for(int i = 1; i <= count; i++) {
result.put( this.item(i) + otro.item(i) , i);
}
return result;
}
}
Herencia de una clase Genérica
 La subclase puede seguir siendo genérica:
 Class Pila<T>
extends ArrayList<T> {…}
 Al heredar de una clase genérica se puede restringir el tipo:
 class ListaOrdenada<T extends Comparable>
extends LinkedList<T> {…}
 Al heredar de una clase genérica se puede instanciar el tipo:
 Class CajaSeguridad
extends LinkedList<Valorable> {…}
Genericidad y Herencia
1. List<Poligono> lp;
2. List<Rectangulo> lr = new List<Rectangulo>();
3. lp = lr; //Error de compilación
Tipos Comodín
 Dado el código de la clase Paint:
Class Paint {
public static void imprimir (List<Poligono> poligonos) {
for(Poligono p : poligonos)
System.out.println(p);
}
}
 El siguiente código daría error:
List<Rectangulo> lr = new LinkedList <Rectangulo> ();
Paint.imprimir(lr); //Error no es una List<Poligono>
 Para que no de error hay que usar el tipo comodín en la declaración del
método
void imprimir (List<? extends Poligono> poligonos)
 Dado el siguiente código:
 Figura f; Rectangulo p;
p = new Rectangulo(...);
f = p;
f.dibujar();
 ¿Como se implementa el método dibujar en la clase Figura?
Clases Abstractas
Clases Abstractas
 public abstract class Figura {
public abstract double perimetro();
public abstract void dibujar();
public abstract void borrar();
public abstract void mover();
public abstract void rotar();
…
}
 public abstract class FiguraCerrada
extends Figura {
public abstract double area();
}
 public abstract class Poligono
extends FiguraCerrada {
ArrayList<Punto> vertices;
public double perimetro() {...}
public void dibujar() {...}
public void borrar() {...}
public void mover() {...}
public void rotar() {...}
}
 public class Rectangulo extends Poligono {
double largo, ancho;
public double area() {...}
public double perimetro {...}
public double diagonal() {...}
}
Figura
+perimetro():double
+dibujar(): void
+borrar(): void
+mover(): void
+rotar():void
FiguraCerrada
Polígono Elipse
Rectángulo Circulo
Rombo
FiguraAbierta
Clases Abstractas
 Toda clase que contenga algún método abstracto (heredado o no) es
abstracta.
 Una clase puede ser abstracta y no contener ningún método abstracto.
 Especifica una funcionalidad que es común a sus subclases.
 Puede ser total o parcialmente abstracta.
 No es posible crear instancias de una clase abstracta, pero si
declarar referencias del tipo de la clase.
 La clase puede incluir la definición del constructor.
 Las clases abstractas sólo tienen sentido en un lenguaje con
comprobación estática de tipos.
Clases Parcialmente Abstractas
 Contienen métodos abstractos y efectivos.
 Los métodos efectivos pueden hacer uso de los abstractos.
 Importante mecanismo para incluir código genérico.
 Incluyen comportamiento abstracto común a todos los descendientes.
 “programming with holes” - Programación con hoyos
 Capturar lo conocido sobre el comportamiento y la estructura
de datos que caracterizan a cierta área de aplicación, dejando
una puerta abierta a la variación
 Factorización del comportamiento común
Clases Parcialmente Abstractas
Método de la
Plantilla
Interfaces
 Son similares a “clases totalmente abstractas” que solo
declaran el comportamiento para un objeto pero no lo
implementan
 Se declaran utilizando la palabra interface.
 public interface Comparable <T> {
public int compararCon(T o2);
}
 Por defectos todos sus métodos son públicos y abstractos.
 Sus atributos solo pueden ser públicos, constantes y de clase.
 public static final int ATRIBUTO = 1;
Interfaces
 Las clases pueden implementar un interfaz
 class Entero implements Comparable<Numero> {
...
Public int compararCon (Numero o2) {
return this.valorEntero() – o2.valorEntero();
...
}
 Cualquier clase efectiva que implemente una interfase debe definir todos
los métodos de dicho interfase
 Si la clase no proporciona la implementación para todos los métodos del
interfase debe ser declarada como abstracta
 No se pueden crear objetos de una Interfaz, pero si puede ser utilizada como tipo
de dato.
 Comparable<Numero> c = new Entero();
Interfaces Parametrización del
Comportamiento
...
Colección <Cuenta> cuentas = Banco.getCuentas();
if (cuentas.buscarCuentasSaldoCero(cuentas)) {
System.out.println(“Hay cuentas con saldo cero”)
}
if (cuentas.buscarCuentasSaldoNegativo(cuentas)) {
System.out.println(“Hay cuentas con saldo negativo”)
}
...
Interfaces Parametrización del
Comportamiento
Interfaces Parametrización del
Comportamiento
Interfaces Parametrización del
Comportamiento
Método de
Composición
<<usa>>
<<implementan>>
Interfaces Parametrización del
Comportamiento
 public interface ICondicion<T> {
public boolean test ( T obj );
}
 public class CuentaSaldoCero implements ICondicion<Cuenta> {
public boolean test ( Cuenta obj ) {
if (obj.getSaldo() == 0.0) {
return true;
}
return false;
}
}
 public class CuentaSaldoNegativo implements ICondicion<Cuenta> {
public boolean test ( Cuenta obj ) {
if (obj.getSaldo() < 0.0) {
return true;
}
return false;
}
}
Interfaces Parametrización del
Comportamiento
...
Colección <Cuenta> cuentas = Banco.getCuentas();
if (cuentas.buscar (new CuentaSaldoCero())) {
System.out.println(“Hay cuentas con saldo cero”);
}
if (cuentas.buscar (new CuentaSaldoNegativo())) {
System.out.println(“Hay cuentas con saldo negativo”);
}
...
Clases Anónimas
• A veces no es necesario usar la clase más de una vez!
Colección <Cuenta> cuentas = Banco.getCuentas();
// buscar cuentas con saldo mayor a 10.000
if (cuentas.buscar (new ICondicion<Cuenta> (){
public boolean test (Cuenta obj) {
return obj.getSaldo > 10000.0;
}
}
) {
System.out.println(“Hay cuentas con saldo mayor a
10.000”);
}
...
Herencia de Interfaces
 Una interfaz puede ser extendida para definir más funcionalidades
necesarias en otros objetos.
public interface Nombrable {
public void setNombre();
public String getNombre();
}
public interface NombrableGraficamente extends Nombrable {
public void graficarNombre();
}
Implementación de múltiples
Interfaces
 Una clase puede implementar más de una interfaz
public interface Nombrable {
public void setNombre(String n);
public String getNombre();
}
public class BienActivoFijo implements Nombrable, Codificable
{
...
}
public interface Codificable {
public void setCodigo(Integer n);
public Integer getCodigo();
}
Herencia Múltiple
 La herencia múltiple permite:
 Extender el sistema de tipos, permitiendo que la clase
heredada sea compatible con los tipos de las clases de cuales
hereda.
 Reutilizar el código de dos o más clases en la clase hija
 En Java no existe la Herencia Múltiple, sin embargo
puede ser esta puede ser emulada a través del uso de
las interfaces
Herencia Múltiple
 Supóngase que un sistema académico posee las clases Alumno y
Profesor de las cuales se desea extender un nuevo objeto llamado
AlumnoAsistente
 En un sistema OO con herencia múltiple la solución sería la siguiente:
Alumno
private String nombre
private String cedula
private Asignatura materias[]
public Alumno(String n, String c, Asignatura m[])
public String getNombre()
public String getCedula()
public Asignatura[] getMaterias()
public void estudiar ()
public void irAClases()
public void rendir()
Profesor
private String nombre
private String cedula
private Asignatura asignaturas[]
public Profesor(String n, String c, Asignatura a[])
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
AlumnoAsistente
Herencia Múltiple
 En Java, un sistema OO sin herencia múltiple, la solución consiste en
heredar de una de las clases e implementar una interfaz que defina el
comportamiento de la otra clase
Alumno
private String nombre
private String cedula
private Asignatura materias[]
public Alumno(String n, String c, Asignatura m[])
public String getNombre()
public String getCedula()
public Asignatura[] getMaterias()
public void estudiar ()
public void irAClases()
public void rendir()
Profesor
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
AlumnoAsistente
Herencia Múltiple
 Sin embargo esta solución es parcial con respecto a la herencia múltiple:
 Se extiende el sistema de tipos pues AlumnoAsistente hereda el
comportamiento de Alumno e implementa el comportamiento definido por la
interface Profesor .
 Sin embargo la reutilización es parcial ya que AlumnoAsistente debe
repetir código de los métodos de Profesor.
Alumno
private String nombre
private String cedula
private Asignatura materias[]
public Alumno(String n, String c, Asignatura m[])
public String getNombre()
public String getCedula()
public Asignatura[] getMaterias()
public void estudiar ()
public void irAClases()
public void rendir()
Profesor
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
AlumnoAsistente
Herencia Múltiple
 Los métodos con el mismo nombre en Alumno e Profesor no entran en
conflicto pues para ambos casos getNombre y getCedula se refieren al
mismo dato
Alumno
private String nombre
private String cedula
private Asignatura materias[]
public Alumno(String n, String c, Asignatura m[])
public String getNombre()
public String getCedula()
public Asignatura[] getMaterias()
public void estudiar ()
public void irAClases()
public void rendir()
Profesor
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
AlumnoAsistente
Herencia Múltiple
 Una solución equivalente a la Herencia Múltiple sería que los objetos de la
clase AlumnoAsistente deleguen la implementación de los métodos de la
interface Profesor en un objeto de alguna clase que los implementen
 Para ello, los objetos de la clase AlumnoAsistente deben componerse de tal
objeto.
Alumno
private String nombre
private String cedula
private Asignatura materias[]
public Alumno(String n, String c, Asignatura m[])
public String getNombre()
public String getCedula()
public Asignatura[] getMaterias()
public void estudiar ()
public void irAClases()
public void rendir()
Profesor
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
AlumnoAsistente
ObjetoQue
Implementa
Profesor
Herencia Múltiple
 Por ejemplo si se tiene una clase ImplProfesor que implementa el
comportamiento de la interface Profesor, los objetos de la clase
AlumnoAsistente pueden componerse de un objeto de la clase
ImplProfesor sobre el cual delegar los comportamientos definidos por la
interface Profesor.
Alumno
private String nombre
private String cedula
private Asignatura materias[]
public Alumno(String n, String c, Asignatura m[])
public String getNombre()
public String getCedula()
public Asignatura[] getMaterias()
public void estudiar ()
public void irAClases()
public void rendir()
Profesor
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
AlumnoAsistente
ObjetoQue
Implementa
Profesor
ImplProfesor
private String nombre
private String cedula
private Asignatura asignaturas[]
public String getNombre()
public String getCedula()
public Asignatura[] getAsignaturas()
public void preprarClases()
public void darClases()
public void tomarExamen()
Herencia Múltiple
1. class AlumnoAsistente extends Alumno implements Profesor {
2. private Profesor p; // referencia al objeto que implementa Profesor
3. public AlumnoAsistente(String nom, String ced, Asignatura[] matAlu, Asignatura[] matProf) {
4. super(nom, ced, matAlu);
5. this.p = new ProfesorImpl(nom, ced, matProf);
6. }
7. // métodos delegados en el objeto que implementa Profesor
8. public Asignatura[] getAsignaturas() { return p.getAsignaturas() }
9. public void enseñar() { p.enseñar () }
10. public void prepararClases() { return p.prepararClase() }
11. public void tomarExamen() { return p.tomarExamen() }
12.
13. // los métodos heredados de Alumno complementan el comportamiento del tipo Alumno
14. // y también complementan la implementación de la interfaz Profesor
15. }
Herencia Múltiple
El siguiente código es válido:
1. AlumnoAsistente alAs = new AlumnoAsistente(n, c, matAl, matPr);
2. // el objeto es de tipo Alumno por heredar de dicha clase
3. Alumno a = alAs;
4. // el objeto es de tipo Profesor por implementar dicha interfaz
5. Profesor p = alAs;

Más contenido relacionado

La actualidad más candente

Sistemas de ecuaciones
Sistemas de ecuacionesSistemas de ecuaciones
Sistemas de ecuaciones
ujgh
 
Lección 1.7 Operaciones Con Funciones Ce L
Lección 1.7 Operaciones Con Funciones Ce LLección 1.7 Operaciones Con Funciones Ce L
Lección 1.7 Operaciones Con Funciones Ce L
Pomales CeL
 
Proyecto de programacion orientada a objetos
Proyecto de programacion orientada a objetosProyecto de programacion orientada a objetos
Proyecto de programacion orientada a objetos
diana_jazmin
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphism
Jussi Pohjolainen
 
Paquetes De Programacion
Paquetes De ProgramacionPaquetes De Programacion
Paquetes De Programacion
tibu85
 

La actualidad más candente (20)

Polimorfismo en Java
Polimorfismo en JavaPolimorfismo en Java
Polimorfismo en Java
 
Sistemas de ecuaciones
Sistemas de ecuacionesSistemas de ecuaciones
Sistemas de ecuaciones
 
Multiple inheritance
Multiple inheritanceMultiple inheritance
Multiple inheritance
 
Programación en N Capas .Net
Programación en N Capas .NetProgramación en N Capas .Net
Programación en N Capas .Net
 
Recorrido de Grafos
Recorrido de GrafosRecorrido de Grafos
Recorrido de Grafos
 
Programación orientada a objetos
Programación orientada a objetosProgramación orientada a objetos
Programación orientada a objetos
 
Recursividad en POO - Java
Recursividad en POO - JavaRecursividad en POO - Java
Recursividad en POO - Java
 
Function overloading and overriding
Function overloading and overridingFunction overloading and overriding
Function overloading and overriding
 
Lección 1.7 Operaciones Con Funciones Ce L
Lección 1.7 Operaciones Con Funciones Ce LLección 1.7 Operaciones Con Funciones Ce L
Lección 1.7 Operaciones Con Funciones Ce L
 
Proyecto de programacion orientada a objetos
Proyecto de programacion orientada a objetosProyecto de programacion orientada a objetos
Proyecto de programacion orientada a objetos
 
Inheritance in Java.pdf
Inheritance in Java.pdfInheritance in Java.pdf
Inheritance in Java.pdf
 
Programación Orientada a Objetos - Otras relaciones entre clases
Programación Orientada a Objetos - Otras relaciones entre clasesProgramación Orientada a Objetos - Otras relaciones entre clases
Programación Orientada a Objetos - Otras relaciones entre clases
 
Sqlite Base de Datos
Sqlite Base de Datos Sqlite Base de Datos
Sqlite Base de Datos
 
Jerarquía de clases, herencia, polimorfismo
Jerarquía de clases, herencia, polimorfismoJerarquía de clases, herencia, polimorfismo
Jerarquía de clases, herencia, polimorfismo
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphism
 
Ppt funciones 4º
Ppt funciones 4ºPpt funciones 4º
Ppt funciones 4º
 
Ejercicios de grafos
Ejercicios de grafosEjercicios de grafos
Ejercicios de grafos
 
Paquetes De Programacion
Paquetes De ProgramacionPaquetes De Programacion
Paquetes De Programacion
 
C++ Inheritance
C++ InheritanceC++ Inheritance
C++ Inheritance
 
Vectores en programación
Vectores en programaciónVectores en programación
Vectores en programación
 

Similar a Herencia_POO.ppt

programacion orientada a objetos
programacion orientada a objetosprogramacion orientada a objetos
programacion orientada a objetos
jent46
 
JAVA_BASICO_modo_consola_introduccion.pptx
JAVA_BASICO_modo_consola_introduccion.pptxJAVA_BASICO_modo_consola_introduccion.pptx
JAVA_BASICO_modo_consola_introduccion.pptx
FamiliaAyluardo
 
programacion orientada a objetos
programacion orientada a objetosprogramacion orientada a objetos
programacion orientada a objetos
ale8819
 
Poo 2009 u2_introd_a_la_poo_2
Poo 2009 u2_introd_a_la_poo_2Poo 2009 u2_introd_a_la_poo_2
Poo 2009 u2_introd_a_la_poo_2
Axel
 
POO-3-Herencia-10-11.pdf
POO-3-Herencia-10-11.pdfPOO-3-Herencia-10-11.pdf
POO-3-Herencia-10-11.pdf
None
 
Programación orientada a objetos con c++
Programación orientada a objetos con c++Programación orientada a objetos con c++
Programación orientada a objetos con c++
Karime Hernández
 

Similar a Herencia_POO.ppt (20)

programacion orientada a objetos
programacion orientada a objetosprogramacion orientada a objetos
programacion orientada a objetos
 
JAVA_BASICO_modo_consola_introduccion.pptx
JAVA_BASICO_modo_consola_introduccion.pptxJAVA_BASICO_modo_consola_introduccion.pptx
JAVA_BASICO_modo_consola_introduccion.pptx
 
Net1 oop vbnet
Net1 oop vbnetNet1 oop vbnet
Net1 oop vbnet
 
Tema2
Tema2Tema2
Tema2
 
Sobrecarga de Métodos y Constructores.pdf
Sobrecarga de Métodos y Constructores.pdfSobrecarga de Métodos y Constructores.pdf
Sobrecarga de Métodos y Constructores.pdf
 
Poo
PooPoo
Poo
 
programacion orientada a objetos
programacion orientada a objetosprogramacion orientada a objetos
programacion orientada a objetos
 
UD2-ConceptosBasicos.pdf
UD2-ConceptosBasicos.pdfUD2-ConceptosBasicos.pdf
UD2-ConceptosBasicos.pdf
 
C ++.ppt
C ++.pptC ++.ppt
C ++.ppt
 
Poo 2009 u2_introd_a_la_poo_2
Poo 2009 u2_introd_a_la_poo_2Poo 2009 u2_introd_a_la_poo_2
Poo 2009 u2_introd_a_la_poo_2
 
Herencia
HerenciaHerencia
Herencia
 
Introducción A C# (VersióN Charla)
Introducción A C# (VersióN Charla)Introducción A C# (VersióN Charla)
Introducción A C# (VersióN Charla)
 
Programación Orientada a Objetos - Unidad 2: clases y objetos
Programación Orientada a Objetos - Unidad 2: clases y objetosProgramación Orientada a Objetos - Unidad 2: clases y objetos
Programación Orientada a Objetos - Unidad 2: clases y objetos
 
Iniciando en java en www.fiec.espol.edu.ec
Iniciando en java  en www.fiec.espol.edu.ecIniciando en java  en www.fiec.espol.edu.ec
Iniciando en java en www.fiec.espol.edu.ec
 
Unidad 3 CLASES, OBJETOS E INTSANCIAS
Unidad 3 CLASES, OBJETOS E INTSANCIASUnidad 3 CLASES, OBJETOS E INTSANCIAS
Unidad 3 CLASES, OBJETOS E INTSANCIAS
 
Herencia y polimorfismo
Herencia y polimorfismoHerencia y polimorfismo
Herencia y polimorfismo
 
Tema 1 2_poo
Tema 1 2_pooTema 1 2_poo
Tema 1 2_poo
 
Clasesyobjetos
ClasesyobjetosClasesyobjetos
Clasesyobjetos
 
POO-3-Herencia-10-11.pdf
POO-3-Herencia-10-11.pdfPOO-3-Herencia-10-11.pdf
POO-3-Herencia-10-11.pdf
 
Programación orientada a objetos con c++
Programación orientada a objetos con c++Programación orientada a objetos con c++
Programación orientada a objetos con c++
 

Herencia_POO.ppt

  • 1. Lenguajes de Programación 2 Programación Orientada a Objetos Herencia Ing. Gustavo Arsenio Sosa Cataldo FACULTAD POLITÉCNICA - UNA
  • 2. • Las clases solas no son suficientes para conseguir: • Reutilización • Generar código que: • Capture los aspectos comunes en grupos de estructuras similares, y • Permita la variación de estructuras de datos y algoritmos subyacentes • Extensibilidad • Necesidad de mecanismos para lograr: • Principio Abierto-Cerrado • Principio de la Elección Única Introducción
  • 3.  Entre algunas clases pueden existir relaciones conceptuales:  Generalización: Se detectan las propiedades comunes.  Extensión: Se amplían las funcionalidades.  Especialización: Se implementan funcionalidades que son especificas  Combinación: Se combinan las funcionalidades de dos o más objetos  ¿Tiene sentido crear una clase a partir de otra(s)?  Herencia: soporte para registrar y utilizar estas relaciones, que posibilita la definición de una clase a partir de otra(s). Introducción
  • 4. Jerarquía de Clases  La herencia permite organizar las clases en jerarquías en las cuales se:  Reutiliza el código de los objetos Padres.  Extiende los tipos de objetos del sistema.  Puede existir una clase “raíz” en la jerarquía de la cual heredan las demás directa o indirectamente.  La clase raíz incluye todas las características comunes a todas las clases  En Java esta clase es la clase Object • boolean equals(Object o) • String toString() • int hashCode()
  • 5. Jerarquía de Clases Object Number Integer Float Double Figura FiguraCerrada Polígono Círculo Rectángulo
  • 6. Herencia entre clases  Si una clase B hereda de otra A, entonces:  B incorpora la estructura (atributos) y comportamiento (métodos) de A,  B puede incluir adaptaciones:  B puede añadir nuevos atributos y métodos  B puede redefinir métodos de A • Refinamiento: Extendiendo el uso de un método de A • Reemplazo: Sobrescribir la implementación de un método de A  B puede implementar un método abstracto en A B hereda de A (A es la superclase y B la subclase) C hereda de B y A B y C son subclases de A B es un descendiente directo de A C es un descendiente indirecto de A
  • 7. Tipos de Herencia • Herencia simple • Una clase puede heredar de una única clase. • Java, C# • Herencia múltiple • Una clase puede heredar de varias clases. • Clases forman un grafo dirigido acíclico • Problemas: • Herencia Repetida. • Conflicto de Nombres. A B C D B C D
  • 8. Problemas de la Herencia Múltiple • Herencia Repetida Ocurre cuando se hereda una misma característica de dos o más líneas de herencia. • Solución 1.Especificar que línea de herencia usar. 2.Herencia Parcial, se elige que heredar de cada línea de herencia. 3.Renombrar características heredadas B a, b C a, c D a, b, c, d A a
  • 9. Problemas de la Herencia Múltiple • Conflicto de Nombres Ocurre cuando se heredan característica diferentes pero con mismo nombre de dos o más líneas de herencia. • Solución 1.Especificar que línea de herencia usar. 2.Herencia Parcial, se elige que heredar de cada línea de herencia. 3.Renombrar características heredadas B b, x C c, x D b, c, x
  • 10. ¿Cómo detectar la herencia durante el diseño? • Generalización (Factorización) Se detectan clases con un comportamiento común (p.e. Libro y Revista son de tipos de Publicación) • Especialización (Abstracción) Se detecta que una clase es un caso especial de otra (p.e. Rectángulo de Polígono)
  • 11. Polígonos y Rectángulos  Tenemos la clase Poligono y necesitamos representar rectángulos:  ¿Debemos crear la clase Rectángulo partiendo de cero?  Podemos aprovechar la existencia de similitudes y particularidades entre ambas clases Polígono vértices : List<Punto> trasladar(int a, int b) dibujar() borrar() perimetro() Polígono(List<Punto> v) Rectángulo lado1 : int lado2 : int perimetro() Rectángulo(List<Punto> v, int l1, int l2) diagonal()
  • 12. Polígonos y Rectángulos  Un rectángulo tiene muchas de las características de un polígono (dibujar(), borrar(), trasladar())  Pero tiene características especiales (diagonal(), lado1, lado2)  Algunas características de polígono pueden implementarse más eficientemente (perímetro()) Polígono vértices : List<Punto> trasladar(int a, int b) dibujar() borrar() perimetro() Polígono(List<Punto> v) Rectángulo lado1 : int lado2 : int perimetro() Rectángulo(Punto vsi, int l1, int l2) diagonal()
  • 13. import gráficos.Punto; Import java.util.List; public class Polígono { //Un polígono es una lista de puntos protected List<Punto> vértices = null; public Polígono(List<Punto> vértices) { this.vértices = vértices; } public void trasladar (double a, double b) {…} public void dibujar() {…} public void borrar() {…} public double perímetro() {…} } Polígonos y Rectángulos
  • 14. public double perímetro() { double total = 0; Punto ant = null; Punto actual = vertices.get(0); for (int i = 1; i < vertices.size(); i++){ ant = actual; actual = vertices.get(i); total = total + actual.distancia(ant); } total = total + actual.distancia(vertices.get(0)); return total; } Polígonos y Rectángulos
  • 15. public class Rectángulo extends Polígono { protected double lado1, lado2; //Nuevos atributos public Rectángulo(Punto vsi; double lado1, double lado2) { this.vértices = new List<Punto>; this.vértices.add(vsi); Punto vsd = new Punto (vsi) vsd.trasladar (0, lado1); this.vertices.add(vsd); ... this.lado1 = lado1; this.lado2 = lado2; } ... Polígonos y Rectángulos
  • 16. public double perímetro() { return (2*(lado1 + lado2 )); } public double diagonal() { return Math.sqrt(Math.pow(lado1, 2) + Math.pow(lado2, 2)) } // ¿Y que pasa con los demás métodos ? }  Todas las demás características de Polígono están disponibles automáticamente para la clase Rectángulo, no es necesario que se repitan. Polígonos y Rectángulos
  • 17. Significado de la herencia Clases Herencia Módulo Mecanismo de Extensión Mecanismo de Reutilización Tipo Mecanismo de Especialización Clasificador de Tipos Sean: • Prop(X): Conjunto de características de la clase X • Dom(X): Conjunto de instancias de la clase X A {Prop(A)} B {Prop(B)} • B Hereda de A  Prop(A)  Prop(B) • Cualquier objeto de B puede ser considerado un objeto de A • Dom(B)  Dom(A)  B es un Subtipo de A • Si se espera un objeto A, podemos recibir o enviar un objeto B.
  • 18. Significado de la herencia Polígono vértices : List<Punto> trasladar(int a, int b) dibujar() borrar() perimetro() Polígono(List<Punto> v) Rectángulo lado1 : int lado2 : int perimetro() Rectángulo(Punto vsi, int l1, int l2) diagonal() 1. Prop(Polígono) = {vértices, trasladar(), dibujar(), borrar(), perímetro()} 2. Prop(Rectángulo) = {vértices, trasladar(), dibujar(), borrar(), perímetro(), lado1, lado2, diagonal()}
  • 19. Significado de la herencia 1. Dom(Polígono) = {recA, recB, polA, polB} 2. Dom(Rectángulo) = {recA, recB, PolB} Rectángulo recA = new Rectángulo(…); Polígono polA = new Polígono(…); Polígono polB = new Rectángulo(…); Rectángulo recB = new Rectángulo(…); Polígono polC = null; Rectangulo recC = null;
  • 20. Significado de los subtipos • El principio de sustitución de Liskov [B. Liskov 88]: • “ Si para cada objeto O1 de tipo S hay un objeto O2 de tipo T, tal que para todos los programas P definidos en términos de T, sí el comportamiento de P no varía cuando se sustituye O2 por O1 entonces S es un subtipo de T ” • Funciones que utilizan referencias a superclases deben ser capaces de utilizar objetos de sus subclases sin saberlo. • public static void dibujarEnPantalla(Polígono p); • dibujarEnPantalla(new Rectangulo(...))
  • 21. Herencia y Creación  Los constructores no se heredan  El constructor de la clase hija refina el comportamiento del constructor del padre  La primera sentencia del constructor de la clase hija SIEMPRE es una llamada al constructor de la clase padre.  La llamada al constructor del padre puede ser:  Implícita: • Si se omite, se llamará implícitamente al constructor por defecto de la clase padre • Equivale a poner como primera sentencia super();  Explícita: • super(); o super(a,b); o . . . • Dependiendo del número y tipo de parámetros se invoca uno de los constructores de la clase padre
  • 22. Acceso protegido en Java • Una subclase no puede acceder a los atributos o métodos privados de su superclase • Para permitir que un método de la subclase pueda acceder a un atributo o un método de la superclase, éste tiene que declararse como protected o public • Resumen de modificadores de acceso: – private – visible sólo en la clase – public – visible a todas las clases – protected – visible a las subclases y a (sub)clases del paquete – default – visible en las clases del paquete
  • 23. Herencia en Java • Toda clase hereda directa o indirectamente de la clase Object • public class Poligono {...} // hereda de Object • public class Rectangulo extends Poligono {...} • Una subclase hereda de su superclase métodos y atributos tanto de clase como de instancia, pero solo puede acceder a las que están definidas como public o protected. • Una subclase puede añadir nuevos métodos y atributos. • Una subclase puede redefinir métodos heredados.
  • 24. Redefinición • La redefinición reconcilia la Reutilización con la Extensibilidad: • “Es raro reutilizar un componente software sin necesidad de cambios” • Los atributos no se pueden redefinir, sólo se OCULTAN • El campo de la superclase todavía existe pero solo se puede acceder por medio de super • Un método de la subclase con la misma signatura y valor de retorno que un método de la superclase lo está REDEFINIENDO. • Si se cambia el tipo de los parámetros se está SOBRECARGANDO el método original y no redefiniendo
  • 25. Redefinición de métodos • Una clase hija puede redefinir un método de la clase padre por dos motivos: • Reemplazo: • Mejorar implementación. • Ej: redefinición de perímetro() en la clase Rectángulo. • Cambiar la Implementación sin variar la semantica. • Refinamiento: • Método del padre + acciones específicas. • La invocación al método del padre se hace usando la palabra super
  • 26. Refinamiento. Ejemplo public class CuentaAhorro extends Cuenta { ... public void ingresar(double cantidad) { //Hace lo mismo que el método de la clase padre super.ingresar(cantidad); //Además hace cosas propias de la CuentaAhorro beneficio = cantidad * PORCENTAJE_BENEFICIO; } }
  • 27. ¿Qué se puede cambiar en la redefinición? • El nivel de acceso • Siempre que se relaje • Puede pasar de protected a public • Por ejemplo, método clone en Object es protected • No se puede pasar de public a private • El tipo de retorno • Siempre que el tipo de retorno del método redefinido sea compatible con el tipo de retorno del método original. • Object  protected Object clone() … (desde Java 1.5) • Punto  public Punto clone() …
  • 28. Restringir la herencia y redefinición  En Java se puede aplicar el modificador final a un método para indicar que no puede ser redefinido.  El modificador final es aplicable a una clase indicando que no se puede heredar de ella.  ¿El modificador final va contra el principio abierto- cerrado?
  • 29. Polimorfismo • El término polimorfismo significa que hay un nombre (referencia, método o clase) y muchos significados diferentes para el mismo (distintas definiciones). • Formas de polimorfismo [Budd’02]: – Polimorfismo de asignación (variables polimorfas) – Polimorfismo puro (función polimorfa) – Polimorfismo ad hoc (sobrecarga) – Polimorfismo de inclusión (redefinición) – Polimorfismo paramétrico (genericidad)
  • 30. Polimorfismo de Asignación  Capacidad de una entidad de referenciar en tiempo de ejecución a instancias de diferentes clases  El conjunto de clases a la que se puede hacer referencia está restringido por la Herencia.  Dada una referencia R de tipo T, en un lenguaje orientado a objetos fuertemente tipado R puede referenciar a cualquier objeto de tipo S, siempre que S sea un subtipo de T.  Number n; n = new Integer(); n = new Double(); n = new BigDecimal();
  • 31. Tipo estático y tipo dinámico • Tipo estático (te): – Tipo asociado en la declaración. Ej: Number n; • Tipo dinámico: – Tipo correspondiente a la clase del objeto conectado a la entidad en tiempo de ejecución. Ej: n = new Float(3.14); • Conjunto de tipos dinámicos (ctd): – Conjunto de posibles tipos dinámicos de una entidad A oa; B ob; C oc; te(oa) = A ctd(oa) = {A,B,C,D,E,F} te(ob) = B ctd(ob) = {B, D, E} te(oc) = C ctd(oc) = {C,F}
  • 32. Entidades y rutinas polimorfas Conexión polimorfa: el origen y el destino tiene tipos diferentes Poligono p; Rectangulo r; a) asignación: p = r; -- p es una entidad polimorfa (polimorfismo de asignación) b) paso de parámetros: void f (Poligono p)… -- f es una rutina polimorfa (polimorfismo puro)
  • 33. Polimorfismo puro vs. Sobrecarga • Funciones sobrecargadas ≠ funciones polimórficas • Sobrecarga: – Dos o mas funciones comparten el nombre y distintos argumentos (nº y tipo). El nombre es polimórfico. – Distintas definiciones (distintos comportamientos) – Función correcta se determina en tiempo de compilación según la signatura. • Funciones polimórficas: – Una única función que puede recibir una variedad de argumentos (comportamiento uniforme). – La ejecución correcta se determina dinámicamente en tiempo de ejecución.
  • 34. Herencia y sistema de tipos A a; B b; C c; D d; ¿Son válidas las siguientes asignaciones? a = b; c = b; a = d
  • 35. Ligadura dinámica ó Enlace dinámico {fδ} redefine f ¿qué versión de f se ejecuta? A oa; … // asignacion de oa oa.f(..); Regla de la ligadura dinámica La forma dinámica del objeto determina la versión de la operación que se aplicará.
  • 36. • La versión de un método en una clase es la introducida por la clase (redefinición u original) o es la heredada. • Ejemplo: Poligono p = new Poligono(); Rectangulo r = new Rectangulo(); Double x; x = p.perimetro() → perimetro POLIGONO x = r.perimetro() → perimetro RECTANGULO p = r; x = p.perimetro() → perimetro RECTANGULO Ligadura dinámica ó Enlace dinámico
  • 37. {fδ} redefine f A a; B b = new B(); D d = new D(); a = b; a.f(); //q versión? a = d a.f(); //q versión? Ligadura dinámica ó Enlace dinámico
  • 38. Ejemplo 2: void visualizar (Figura [] figuras){ for (Figura figura : figuras) figura.dibujar(); } ¿Qué sucede si aparece un nuevo tipo de figura? ¿Qué relación existe entre ligadura dinámica y comprobación estática de tipos? Sea el mensaje x.f (), la comprobación estática de tipos garantiza que al menos el mensaje sea válido, y la ligadura dinámica garantiza que se ejecutará la versión más apropiada. Ligadura dinámica ó Enlace dinámico
  • 39. Ejemplo ligadura dinámica, super y this class Uno { public int test(){return 1;} public int result1(){return this.test();} } class Dos extends Uno{ public int test(){return 2;} } class Tres extends Dos{ public int result2(){return this.result1();} public int result3(){return super.test();} } class Cuatro extends Tres{ public int test(){return 4;} }
  • 40. public class PruebaSuperThis{ public static void main (String args[]){ Uno ob1 = new Uno(); Dos ob2 = new Dos(); Tres ob3 = new Tres(); Cuatro ob4 = new Cuatro(); System.out.println("ob1.test = "+ ob1.test()); System.out.println("ob1.result1 = " + ob1.result1()); System.out.println("ob2.test = " + ob2.test()); System.out.println("ob2.result1 = " + ob2.result1()); System.out.println("ob3.test = " + ob3.test()); System.out.println("ob4.result1 = " + ob4.result1()); System.out.println("ob3.result2 = " + ob3.result2()); System.out.println("ob4.result2 = " + ob4.result2()); System.out.println("ob3.result3 = " + ob3.result3()); System.out.println("ob4.result3 = " + ob4.result3()); } } Ejemplo ligadura dinámica, super y this 1
  • 41. {fδ} redefine f A a; B b = new B(); D d = new D(); a = b; a.f(); //versión B a = d a.f(); //versión D Principio de la Elección Única Principio de la Elección Única Gracias al polimorfismo el modulo A conoce todas sus variantes por medio del enlace dinámico se aplica la versión correcta de una operación
  • 42. Código Genérico  Un único código con diferentes interpretaciones en tiempo de ejecución  Es fundamental que el lenguaje soporte:  Polimorfismo  Ligadura Dinámica  El mismo código ejecutará cosas distintas en función del Tipo Dinámico de la entidad polimórfica (ligadura dinámica)  Gracias al polimorfismo y la ligadura dinámica se satisface el criterio de reutilización de Variación de la Implementación.
  • 43. Código Genérico  class CalculadorDeCostos { /* Los objetos de esta clase calculan el costo de diversas cosas */ ... public double precioDeVallado(Parcela p) { Poligono forma = p.getForma(); double costo = forma.getPerimetro() * this.getCostoVallado(); return costo; } }  forma puede ser cualquier objeto de tipo Poligono.  El mensaje forma.getPerimetro() tendrá diferentes significados según sea el tipo dinámico de forma.
  • 44. Copias de Objetos  Tipos de copia:  Copia superficial: los campos de la copia son exactamente iguales a los del objeto original.  Copia profunda: los campos primitivos de la copia son iguales y las referencias son copias de los objetos referenciados por el original.  Adaptada: adaptada a la necesidad de la aplicación.
  • 45. Copia superficial  Alias Dinámico: Incorrecto al compartir las últimas operaciones  No deberían tener el mismo valor de código
  • 46. Copia profunda  No tiene sentido duplicar el objeto Persona  No deberían tener el mismo código
  • 48. Copia adaptada  Para implementar la copia se debe redefinir el método:  protected Object clone();  class Cuenta { ... public Cuenta clone() { Cuenta clon = super.clone(); // copia superficial clon.codigo = Cuenta.getSgteCodigo(); // código nuevo clon.ultOper = new ArrayList<Integer>(); // se copian las operaciones for (Integer oper : this.ultOper) { clon.ultOper.add(new Integer(oper)); } return clon; } }
  • 49. Igualdad de Objetos  Tipos de igualdad:  Superficial: los campos primitivos de los dos objetos son iguales y las referencias apuntan a los mismos objetos (==).  Profunda: los campos primitivos son iguales y las referencias no son los mismos objetos pero estos son iguales en profundidad (equals).  Adaptada: adaptada a las necesidades de la aplicación.  ¿Cuándo dos cuentas son iguales?
  • 50. Igualdad de Objetos  Para implementar la comparación se debe redefinir el método:  public boolean equals(Object o2);  class Cuenta { ... public boolean equals(Object o2) { if(!(o2 instanceof Cuenta) ) return false; Cuenta c2 = (Cuenta) o2; if ( this.saldo != c2.saldo || this.titular != c2.titular || this.ultOper.size() != c2.ultOper.size() ) return false; for (int i = 0; i < this.ultOper.size() ; i++) { if (! this.ultOper.get(i).equals( c2.ultOper.get(i)) ) return false; } return true; } }
  • 51. Genericidad restringida  Public class Vector <T> { private int count; public T item( int i ){…} public void put (T v, int index){…} public Vector<T> suma (Vector<T> otro){ Vector<T> result= new Vector<T>(); for(int i = 1; i <= count; i++) { result.put( this.item(i) + otro.item(i) , i); } return result; } }
  • 52. Genericidad restringida  Public class Vector <T extends Number> { private int count; public T item( int i ){…} public void put (T v, int index){…} public Vector<T> suma (Vector<T> otro){ Vector<T> result = new Vector<T>(); for(int i = 1; i <= count; i++) { result.put( this.item(i) + otro.item(i) , i); } return result; } }
  • 53. Herencia de una clase Genérica  La subclase puede seguir siendo genérica:  Class Pila<T> extends ArrayList<T> {…}  Al heredar de una clase genérica se puede restringir el tipo:  class ListaOrdenada<T extends Comparable> extends LinkedList<T> {…}  Al heredar de una clase genérica se puede instanciar el tipo:  Class CajaSeguridad extends LinkedList<Valorable> {…}
  • 54. Genericidad y Herencia 1. List<Poligono> lp; 2. List<Rectangulo> lr = new List<Rectangulo>(); 3. lp = lr; //Error de compilación
  • 55. Tipos Comodín  Dado el código de la clase Paint: Class Paint { public static void imprimir (List<Poligono> poligonos) { for(Poligono p : poligonos) System.out.println(p); } }  El siguiente código daría error: List<Rectangulo> lr = new LinkedList <Rectangulo> (); Paint.imprimir(lr); //Error no es una List<Poligono>  Para que no de error hay que usar el tipo comodín en la declaración del método void imprimir (List<? extends Poligono> poligonos)
  • 56.  Dado el siguiente código:  Figura f; Rectangulo p; p = new Rectangulo(...); f = p; f.dibujar();  ¿Como se implementa el método dibujar en la clase Figura? Clases Abstractas
  • 57. Clases Abstractas  public abstract class Figura { public abstract double perimetro(); public abstract void dibujar(); public abstract void borrar(); public abstract void mover(); public abstract void rotar(); … }  public abstract class FiguraCerrada extends Figura { public abstract double area(); }  public abstract class Poligono extends FiguraCerrada { ArrayList<Punto> vertices; public double perimetro() {...} public void dibujar() {...} public void borrar() {...} public void mover() {...} public void rotar() {...} }  public class Rectangulo extends Poligono { double largo, ancho; public double area() {...} public double perimetro {...} public double diagonal() {...} } Figura +perimetro():double +dibujar(): void +borrar(): void +mover(): void +rotar():void FiguraCerrada Polígono Elipse Rectángulo Circulo Rombo FiguraAbierta
  • 58. Clases Abstractas  Toda clase que contenga algún método abstracto (heredado o no) es abstracta.  Una clase puede ser abstracta y no contener ningún método abstracto.  Especifica una funcionalidad que es común a sus subclases.  Puede ser total o parcialmente abstracta.  No es posible crear instancias de una clase abstracta, pero si declarar referencias del tipo de la clase.  La clase puede incluir la definición del constructor.  Las clases abstractas sólo tienen sentido en un lenguaje con comprobación estática de tipos.
  • 59. Clases Parcialmente Abstractas  Contienen métodos abstractos y efectivos.  Los métodos efectivos pueden hacer uso de los abstractos.  Importante mecanismo para incluir código genérico.  Incluyen comportamiento abstracto común a todos los descendientes.  “programming with holes” - Programación con hoyos  Capturar lo conocido sobre el comportamiento y la estructura de datos que caracterizan a cierta área de aplicación, dejando una puerta abierta a la variación  Factorización del comportamiento común
  • 61. Interfaces  Son similares a “clases totalmente abstractas” que solo declaran el comportamiento para un objeto pero no lo implementan  Se declaran utilizando la palabra interface.  public interface Comparable <T> { public int compararCon(T o2); }  Por defectos todos sus métodos son públicos y abstractos.  Sus atributos solo pueden ser públicos, constantes y de clase.  public static final int ATRIBUTO = 1;
  • 62. Interfaces  Las clases pueden implementar un interfaz  class Entero implements Comparable<Numero> { ... Public int compararCon (Numero o2) { return this.valorEntero() – o2.valorEntero(); ... }  Cualquier clase efectiva que implemente una interfase debe definir todos los métodos de dicho interfase  Si la clase no proporciona la implementación para todos los métodos del interfase debe ser declarada como abstracta  No se pueden crear objetos de una Interfaz, pero si puede ser utilizada como tipo de dato.  Comparable<Numero> c = new Entero();
  • 63. Interfaces Parametrización del Comportamiento ... Colección <Cuenta> cuentas = Banco.getCuentas(); if (cuentas.buscarCuentasSaldoCero(cuentas)) { System.out.println(“Hay cuentas con saldo cero”) } if (cuentas.buscarCuentasSaldoNegativo(cuentas)) { System.out.println(“Hay cuentas con saldo negativo”) } ...
  • 66. Interfaces Parametrización del Comportamiento Método de Composición <<usa>> <<implementan>>
  • 67. Interfaces Parametrización del Comportamiento  public interface ICondicion<T> { public boolean test ( T obj ); }  public class CuentaSaldoCero implements ICondicion<Cuenta> { public boolean test ( Cuenta obj ) { if (obj.getSaldo() == 0.0) { return true; } return false; } }  public class CuentaSaldoNegativo implements ICondicion<Cuenta> { public boolean test ( Cuenta obj ) { if (obj.getSaldo() < 0.0) { return true; } return false; } }
  • 68. Interfaces Parametrización del Comportamiento ... Colección <Cuenta> cuentas = Banco.getCuentas(); if (cuentas.buscar (new CuentaSaldoCero())) { System.out.println(“Hay cuentas con saldo cero”); } if (cuentas.buscar (new CuentaSaldoNegativo())) { System.out.println(“Hay cuentas con saldo negativo”); } ...
  • 69. Clases Anónimas • A veces no es necesario usar la clase más de una vez! Colección <Cuenta> cuentas = Banco.getCuentas(); // buscar cuentas con saldo mayor a 10.000 if (cuentas.buscar (new ICondicion<Cuenta> (){ public boolean test (Cuenta obj) { return obj.getSaldo > 10000.0; } } ) { System.out.println(“Hay cuentas con saldo mayor a 10.000”); } ...
  • 70. Herencia de Interfaces  Una interfaz puede ser extendida para definir más funcionalidades necesarias en otros objetos. public interface Nombrable { public void setNombre(); public String getNombre(); } public interface NombrableGraficamente extends Nombrable { public void graficarNombre(); }
  • 71. Implementación de múltiples Interfaces  Una clase puede implementar más de una interfaz public interface Nombrable { public void setNombre(String n); public String getNombre(); } public class BienActivoFijo implements Nombrable, Codificable { ... } public interface Codificable { public void setCodigo(Integer n); public Integer getCodigo(); }
  • 72. Herencia Múltiple  La herencia múltiple permite:  Extender el sistema de tipos, permitiendo que la clase heredada sea compatible con los tipos de las clases de cuales hereda.  Reutilizar el código de dos o más clases en la clase hija  En Java no existe la Herencia Múltiple, sin embargo puede ser esta puede ser emulada a través del uso de las interfaces
  • 73. Herencia Múltiple  Supóngase que un sistema académico posee las clases Alumno y Profesor de las cuales se desea extender un nuevo objeto llamado AlumnoAsistente  En un sistema OO con herencia múltiple la solución sería la siguiente: Alumno private String nombre private String cedula private Asignatura materias[] public Alumno(String n, String c, Asignatura m[]) public String getNombre() public String getCedula() public Asignatura[] getMaterias() public void estudiar () public void irAClases() public void rendir() Profesor private String nombre private String cedula private Asignatura asignaturas[] public Profesor(String n, String c, Asignatura a[]) public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen() AlumnoAsistente
  • 74. Herencia Múltiple  En Java, un sistema OO sin herencia múltiple, la solución consiste en heredar de una de las clases e implementar una interfaz que defina el comportamiento de la otra clase Alumno private String nombre private String cedula private Asignatura materias[] public Alumno(String n, String c, Asignatura m[]) public String getNombre() public String getCedula() public Asignatura[] getMaterias() public void estudiar () public void irAClases() public void rendir() Profesor public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen() AlumnoAsistente
  • 75. Herencia Múltiple  Sin embargo esta solución es parcial con respecto a la herencia múltiple:  Se extiende el sistema de tipos pues AlumnoAsistente hereda el comportamiento de Alumno e implementa el comportamiento definido por la interface Profesor .  Sin embargo la reutilización es parcial ya que AlumnoAsistente debe repetir código de los métodos de Profesor. Alumno private String nombre private String cedula private Asignatura materias[] public Alumno(String n, String c, Asignatura m[]) public String getNombre() public String getCedula() public Asignatura[] getMaterias() public void estudiar () public void irAClases() public void rendir() Profesor public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen() AlumnoAsistente
  • 76. Herencia Múltiple  Los métodos con el mismo nombre en Alumno e Profesor no entran en conflicto pues para ambos casos getNombre y getCedula se refieren al mismo dato Alumno private String nombre private String cedula private Asignatura materias[] public Alumno(String n, String c, Asignatura m[]) public String getNombre() public String getCedula() public Asignatura[] getMaterias() public void estudiar () public void irAClases() public void rendir() Profesor public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen() AlumnoAsistente
  • 77. Herencia Múltiple  Una solución equivalente a la Herencia Múltiple sería que los objetos de la clase AlumnoAsistente deleguen la implementación de los métodos de la interface Profesor en un objeto de alguna clase que los implementen  Para ello, los objetos de la clase AlumnoAsistente deben componerse de tal objeto. Alumno private String nombre private String cedula private Asignatura materias[] public Alumno(String n, String c, Asignatura m[]) public String getNombre() public String getCedula() public Asignatura[] getMaterias() public void estudiar () public void irAClases() public void rendir() Profesor public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen() AlumnoAsistente ObjetoQue Implementa Profesor
  • 78. Herencia Múltiple  Por ejemplo si se tiene una clase ImplProfesor que implementa el comportamiento de la interface Profesor, los objetos de la clase AlumnoAsistente pueden componerse de un objeto de la clase ImplProfesor sobre el cual delegar los comportamientos definidos por la interface Profesor. Alumno private String nombre private String cedula private Asignatura materias[] public Alumno(String n, String c, Asignatura m[]) public String getNombre() public String getCedula() public Asignatura[] getMaterias() public void estudiar () public void irAClases() public void rendir() Profesor public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen() AlumnoAsistente ObjetoQue Implementa Profesor ImplProfesor private String nombre private String cedula private Asignatura asignaturas[] public String getNombre() public String getCedula() public Asignatura[] getAsignaturas() public void preprarClases() public void darClases() public void tomarExamen()
  • 79. Herencia Múltiple 1. class AlumnoAsistente extends Alumno implements Profesor { 2. private Profesor p; // referencia al objeto que implementa Profesor 3. public AlumnoAsistente(String nom, String ced, Asignatura[] matAlu, Asignatura[] matProf) { 4. super(nom, ced, matAlu); 5. this.p = new ProfesorImpl(nom, ced, matProf); 6. } 7. // métodos delegados en el objeto que implementa Profesor 8. public Asignatura[] getAsignaturas() { return p.getAsignaturas() } 9. public void enseñar() { p.enseñar () } 10. public void prepararClases() { return p.prepararClase() } 11. public void tomarExamen() { return p.tomarExamen() } 12. 13. // los métodos heredados de Alumno complementan el comportamiento del tipo Alumno 14. // y también complementan la implementación de la interfaz Profesor 15. }
  • 80. Herencia Múltiple El siguiente código es válido: 1. AlumnoAsistente alAs = new AlumnoAsistente(n, c, matAl, matPr); 2. // el objeto es de tipo Alumno por heredar de dicha clase 3. Alumno a = alAs; 4. // el objeto es de tipo Profesor por implementar dicha interfaz 5. Profesor p = alAs;