Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto...

31
Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización y generalización. La herencia es un tipo de relación “es un” donde cada clase puede tener una clase ancestro y clases descendientes. Uno de los mecanismos de abstracción es el de generalización que tiene que ver con las taxonomías, permite definir una clase o tipo como un caso general de varias clases o tipos. Por ejemplo, defino la clase de los cuadriláteros a partir de los paralelogramos, rectángulos y rombos. La operación inversa se llama especialización y es la que permite definir clases como casos particulares de otras más generales.

Transcript of Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto...

Page 1: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Concepto de Herencia.

La herencia es un concepto central de la POO. Responde al mecanismo de especialización y generalización. La herencia es un tipo de relación “es un” donde cada clase puede tener una clase ancestro y clases descendientes.

Uno de los mecanismos de abstracción es el de generalización que tiene que ver con las taxonomías, permite definir una clase o tipo como un caso general de varias clases o tipos. Por ejemplo, defino la clase de los cuadriláteros a partir de los paralelogramos, rectángulos y rombos. La operación inversa se llama especialización y es la que permite definir clases como casos particulares de otras más generales.

Page 2: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Gracias a este tipo de relación cada clase hereda atributos y comportamiento de su clase ancestro.

PezAve

NoMamifero

Animal

Mamifero

PerroCaballo

Page 3: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

En este conjunto de clases se plantea la relación de herencia. Cada clase tiene su superclase o clase ancestro (clase superior en la jerarquía) y cada clase puede tener una o más subclases (clases inferiores en la jerarquía).

Los constructores no se heredan

Ejercicio: Se debe implementar un generador de listados de los clientes de una empresa que debe ser armado en un archivo PDF a partir de la BD. la BD. Este listado en pdf debe ser posible imprimirlo por impresora y enviarlo por mail.

Se deben definir las clases necesarias para dar soporte a este requerimiento.

Page 4: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Reutilización y extensión Llamamos reutilización al uso de clases u componentes desarrollados y probados en un determinado contexto, para incorporar esa funcionalidad en una aplicación diferente a la de origen.

La extensión se basa en aprovechar las clases desarrolladas para una aplicación, utilizándolas en la construcción de nuevas clases para la misma u otra aplicación. La extensión es una forma de aplicar la reutilización ya que aprovechamos la definición de una clase para luego agregar más funcionalidad o modificar alguna existente.

Page 5: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Reutilización y extensión Cuando usamos herencia, lo que se está reutilizando es la interfaz, que es lo que ven los clientes. Cualquier mensaje que pueda recibir un objeto de la clase ancestro lo podrá recibir también uno de las clases descendientes, a demás de poder recibir mensajes que invoquen métodos que sólo existen en la clase descendiente. De aquí deducimos que los métodos declarados en la clase descendiente no van a estar en la clase ancestro.

Page 6: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Consideraciones en la aplicación de Herencia

1. Una clase hereda todos los miembros de su superclase, excepto los constructores. Esto se debe principalmente a que la estructura interna de datos de un objeto de una subclase, estará formada por los atributos que ella define y por los heredados de su superclase.

2. Una subclase no tiene acceso directo a los miembros privados (private) de su superclase. Esto debe ser así para cumplir con el principio de encapsulamiento (este concepto estudiaremos más adelante).

3. Una subclase puede tener acceso directo a los miembros públicos (public) y protegidos (protected) de su superclase.

Page 7: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Consideraciones en la aplicación de Herencia

4. En el caso de que la subclase pertenezca al mismo paquete que el de su superclase, si puede tener acceso a los miembros predeterminados (miembros sin modificador de acceso establecido por el programador).

5. Una subclase puede agregar sus propios miembros, a pesar de los ya heredados desde su superclase.

6. No se puede aplicar la herencia múltiple en Java, una clase puede heredar de una sola clase.

Page 8: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Consideraciones en la aplicación de Herencia

7. Si se quiere que una clase no permita que se extienda de la misma, que no posea subclases, se la debe declarar cómo final. Por ejemplo:

public final class Util {//Cuerpo de la clase

}

Page 9: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Interfaces

Una interfaz define un conjunto de mensajes que pueden recibir las clasesque la implementan, donde cada una debe responder de acuerdo a laimplementación que dio a cada uno de estos métodos. En conjunto estasoperaciones especifican un servicio.

Sintaxis para definir una interfaz en Java:

interface y el cuerpo de la interfaz entre llaves {}.[public] interface nombre_interfaz [extends interfaces]{

//Cuerpo de la interfaz}

Page 10: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Interfaces

La interfaz puede extender de otras interfaces, no de clases. Si no seespecifica el modificador de acceso public, la interfaz sólo será accedida paralas clases definidas en el mismo paquete.

El cuerpo de la interfaz posee las siguientes características:

• Sólo puede poseer atributos estáticos y con valor constante. En el caso deque no se especifique que el atributo es estático (static) y constante (final)automáticamente se establece con estas características. El modificador de acceso es público.

Page 11: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Interfaces

• Los métodos deben ser públicos (public) y no pueden ser estáticos o de clase. Si no especifica el modificador de acceso public, automáticamente el método se establece como tal. Los métodos no son implementados, solo se especifica hasta los parámetros que puede recibir entre (…) y luego se finaliza con un “;”.

public int metodo_prueba ([lista_parametros]);

Las clases que implementen la interfaz son las que implementarán el cuerpodel método.

Page 12: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Interfaces

• La palabra extends permite que una interfaz extienda de otra; a continuación de la palabra extends se especifica la lista de interfaces

• Una interfaz hereda todas las constantes y métodos de las interfaces de las cuales deriva, si en la interfaz existe un método o atributo con igual nombre que algunos de los métodos o atributos de las interfaces que deriva, vale el método o atributo de la interfaz que estamos definiendo. El mismo análisis vale para una clase que implementa una interfaz.

Page 13: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

Interfaces

Page 14: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

ENCAPSULAMIENTO

• Se debe tener antes en claro el concepto de abstracción y ocultamiento de la implementación.

• La abstracción consiste en identificar las características esenciales de un objeto, así como su comportamiento. De esta manera logramos definir las distintas clases de nuestro sistema y la relación entre las mismas.

• El ocultamiento de la implementación tiene por objetivo que el cliente no use la estructura interna de la clase. Se puede usar nada más que la interfaz de nuestra clase pero no la implementación. El ocultamiento nos permite restringir y controlar el uso de la clase.

Page 15: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Diseño y programación de herencia de clases:

ENCAPSULAMIENTO

• El encapsulamiento tiene por objetivo concentrar las características y comportamiento de un objeto en un solo lugar, es decir, en una clase. Cada clase se preocupa de sí misma y tiene todo encapsulado en su interior, cada clase debe desacoplar a las demás de sus detalles internos, solo debemos saber cómo usar sus servicios a través de su interfaz. Evidentemente esto nos permite dominar la complejidad y el concepto de encapsulamiento se cumple aplicando los de abstracción (concentrando las características esenciales y comportamiento de un objeto en una clase) y ocultamiento de implementación (ocultando los detalles internos de la clase, evitar que el cliente sea dependiente de una implementación en particular)

Page 16: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

POLIMORFISMO• Polimorfismo quiere decir “muchas formas”.

• En POO llamamos polimorfismo a la posibilidad que tienen los métodos de mantener una respuesta unificada, manteniendo la misma semántica aunque la implementación puede ser distinta, a través del establecimiento de la jerarquía de clases (herencia).

GeneradorListadoMail

generarListadoClientes()

GeneradorListadoArchivo

generarListadoClientes()

GeneradorListadoMonitor

generarListadoClientes()

GeneradorListadoImpresora

generarListadoClientes()

GeneradorListado

generarListadoClientes()

Page 17: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Redefinición y Sobrecarga• La redefinición es una funcionalidad que se usa cuando el

comportamiento de la clase ancestro no es exactamente igual para la descendiente.

• Análisis de método generarListadoClientes() en la clase ancestro GeneradorListado. Este comportamiento no es el esperado que realice el GeneradorListadoImpresora ni tampoco los demás generadores, de aquí donde el método generarListadoClientes() requiere un comportamiento diferente para cada una de las subclases.

• En el caso de que se desee acceder al método de la clase ancestro dentro de una clase descendiente, se debe realizar con la palabra super más .generarListadoClientes(), es decir, super.generarListadoClientes() con esto estamos invocando al método de la clase ancestro desde la subclase, lo que permite en tiempo de ejecución saber a qué clase pertenece el método que se está invocando.

Page 18: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Redefinición y Sobrecarga• La redefinición es una funcionalidad que se usa cuando el

comportamiento de la clase ancestro no es exactamente igual para la descendiente.

• Análisis de método generarListadoClientes() en la clase ancestro GeneradorListado. Este comportamiento no es el esperado que realice el GeneradorListadoImpresora ni tampoco los demás generadores, de aquí donde el método generarListadoClientes() requiere un comportamiento diferente para cada una de las subclases.

• En el caso de que se desee acceder al método de la clase ancestro dentro de una clase descendiente, se debe realizar con la palabra super más .generarListadoClientes(), es decir, super.generarListadoClientes() con esto estamos invocando al método de la clase ancestro desde la subclase, lo que permite en tiempo de ejecución saber a qué clase pertenece el método que se está invocando.

Page 19: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Redefinición y Sobrecarga• Debemos utilizar la redefinición cuando la subclase debe presentar un

comportamiento diferente que la clase ancestro, por razones de eficiencia o porque la redefinición completará la funcionalidad que ya brinda la superclase. Podemos observar que la redefinición se produce cuando se desea realizar un cambio de comportamiento no de estructura, por eso se redefinen métodos y no atributos.

• En Java los métodos se redefinen reescribiendo el método en la clase derivada, el mismo método que está en la clase ancestro (igual modificador de acceso, tipo de dato de retorno, igual nombre, igual tipo y cantidad de parámetros), modificando únicamente el cuerpo del método. Los métodos privados no se pueden redefinir.

• En el caso de que no se quiera que un método sea redefinido se debe anteponer al nombre del método la palabra final.

Page 20: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Redefinición y Sobrecarga• En el caso de que en una clase descendiente defina un método de la clase

ancestro con una firma diferente (manteniendo el mismo nombre), esto no provoca una redefinición del método sino una sobrecarga. Es un método que está disponible en la clase descendiente.

Page 21: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Clases y métodos abstractos. • Un método abstracto es aquel que no posee implementación y que nunca

será invocado sobre una instancia de la clase donde se encuentra definido como tal.

• Puede que nunca se invoque al método generarListadoClientes de la clase ancestro en el caso de que solo importe el formato en que genere cada una de las subclases, por lo tanto no deberíamos brindar ninguna implementación a este método en la superclase GeneradorListado, y talvez una alternativa sería eliminar este método y declararlo en cada subclase, pero ¿qué ocurre si existe un método en la clase ancestro que utiliza el método generarListadoClientes?

public void registrarGenerarListado(){ generarListadoClientes();

//Instrucciones para registrar cuando se generó el //listado

}

Page 22: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Clases y métodos abstractos. • Los métodos abstractos siempre deben ser redefinidos por la

subclase, son virtuales y son necesarios cuando en la clase ancestro hay que utilizarlos en la implementación de otro método.

• En Java un método abstracto se define de la siguiente manera:

abstract public void generarListadoClientes();

• Podemos deducir que los métodos de una interfaz, por definición son abstractos.

Page 23: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Clases y métodos abstractos. • Una clase abstracta es aquella sobre la cual no tiene sentido crear

instancias.

• Si las clases descendientes de GeneradorListado cubren todas las posibilidades de generación, no tiene sentido permitir crear instancias de esta clase. Por lo tanto a esta clase la definimos como abstracta.

• Estos tipos de clases tienen como finalidad la declaración de atributos y métodos comunes que luego serán utilizados por las clases descendientes. Se definen estas clases para generalizar estructura y comportamiento comunes para varias clases descendientes. A diferencia de las interfaces aquí pueden existir métodos con implementación y que invoquen a los métodos abstractos.Para que una clase posea un método abstracto, debe estar

definida como abstracta también.public abstract class GeneradorListado{

//cuerpo de la clase}

Page 24: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Clases y métodos abstractos. • Si una clase abstracta no necesita implementar todos sus métodos o

atributos, sería mejor definir una interfaz. Por eso decimos que una interfaz es un caso especial de clase abstracta.

• Esta es la definición final de la clase GeneradorListado:

public abstract class GeneradorListado { //Atributos

public abstract void generarListadoClientes(); public void registrarGenerarListado(){ generarListadoClientes(); //Instrucciones para registrar cuando se generó el listado System.out.println("Registro de información sobre

generación de listado"); }

}

Page 25: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

• En Java podemos hacer transformaciones entre tipos. Estas transformaciones son importantes tenerlas en cuenta cuando estamos utilizando polimorfismo y la vinculación tardía.

GeneradorListado unGeneradorListado=new GeneradorListadoImpresora(); GeneradorListadoImpresora generador= (GeneradorListadoImpresora) unGeneradorListado;

• Estamos transformando de GeneradorListado a GeneradorListadoImpresora. Necesitamos hacer esto para utilizar alguna funcionalidad particular de la clase GeneradorListadoImpresora que no está en la clase ancestro GeneradorListado. Aquí estamos haciendo una transformación hacia abajo de la jerarquía. Podemos hacer esta transformación porque unGeneradorListado hace referencia en realidad a un GeneradorListadoImpresora.

Page 26: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

GeneradorListado unGeneradorListado=new GeneradorListadoMail();

GeneradorListadoImpresora generador= (GeneradorListadoImpresora) unGeneradorListado;

Un unGeneradorListado hace referencia a un GeneradorListadoMail, por lotanto no es posible la transformación a GeneradorListadoImpresora, selanzará una excepción en tiempo de ejecución.

Estos tipos de transformaciones se llaman moldeo, proveniente del inglés “tocast”.

Page 27: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

En Java existe el moldeo automático, que se da cuando se realiza unatransformación del tipo de la clase descendiente a la clase ancestro.

unGeneradorListado=unGeneradorListadoImpresora;

Como la clase GeneradorListadoImpresora extiende de GeneradorListado,se puede hacer este tipo de transformación.

Page 28: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

Ejemplo:

GeneradorListado generadorImpresora=new GeneradorListadoImpresora();GeneradorListadoMonitor generadorMonitor=new GeneradorListadoMonitor();

GeneradorListado generadorListado_1=generadorImpresora;generadorImpresora=generadorListado_1;

GeneradorListado generadorListado_2=generadorMonitor; generadorMonitor=generadorListado_2;

Page 29: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

Cuando aplicamos herencia, se recomienda que declaremos a los objetos conel tipo de la clase base y luego en al invocar el constructor especificamos aque subclase queremos que el objeto haga referencia, luego si necesitamosacceder a algún miembro exclusivo de la subclase realizamos el moldeo a lasubclase.

Page 30: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

Java también nos permite saber el tipo de un objeto en tiempo de ejecución.Esto se conoce como RTTI (run-time type information). Podemos saber eltipo de un objeto con el operador instanceof:

if(objeto instanceof GeneradorListadoImpresora){ ((GeneradorListadoImpresora)objeto).generarListadoClientes();

}

También podemos hacer la misma comprobación de la siguiente manera:

if(objeto.getClass()==GeneradorListadoImpresora.class){ ((GeneradorListadoImpresora)objeto).generarListadoClientes();

}

Page 31: Diseño y programación de herencia de clases: Concepto de Herencia. La herencia es un concepto central de la POO. Responde al mecanismo de especialización.

Transformaciones e información de tipos en tiempo de ejecución.

La diferencia es que con la primera comprobación nos aseguramos de queobjeto sea del tipo GeneradorListadoImpresora o algún descendiente de lamisma. Con la segunda forma de comprobar nos aseguramos que objeto seaexactamente del tipo GeneradorListadoImpresora y no de ninguna clasedescendiente. Téngase en cuenta que una vez que un objeto es instanciadoposee un tipo que es inmutable durante el ciclo de vida del objeto.

No son muchos los casos en que se utiliza esta forma de trabajar, coninformación de tipo. Por lo general siempre debemos ver la forma dereemplazar esta solución por el uso del polimorfismo.