Archivos de la categoría ‘10. Programación orientada a objetos (y II)’

Materiales para la Unidad 10

Publicado: Lunes, 21 \21\UTC junio \21\UTC 2010 en 10. Programación orientada a objetos (y II)
Presentación

Transcripción de la parte teórica de la unidad 10

Teoría

Con el tema 10 finalizamos el estudio de los principios básicos de la programación orientada a objetos: trataremos la herencia y el manejo de excepciones.

El tema de la herencia corresponde al apartado 5.7 del material que utilizamos. En este tema se estudia la herencia y el polimorfismo. No os asustéis, se les dan nombres “extravagantes” para que parezca algo difícil de entender. Pero con la base que tenéis de SGBD (de nuevo) tenéis casi todo el camino recorrido.

El concepto de herencia lo habéis tratado en SGBD en lo que allí se denomina especialización/generalización (entidad/superentidad/subentidad). La idea es la misma: existen una serie de elementos que heredan características de elementos “padre” y que tienen algunas especiales propias. En SGBD esos elementos son las entidades y en DFSI son las clases. Durante esta semana pondré algo en el blog sobre esto, seguidme la pista.

No quiero complicaros con conceptos más “fuertes”, así que el apartado 5.7.6 (interfaces) no lo leáis. Sólo para el que le interese, comentar que es la manera que Java puede hacer herencia múltiple, es decir, que una clase herede características de “varios padres”.

El tema del manejo de excepciones se trata en el apartado 7 (excepciones) del material complementario “curso de Java”. Veréis cómo la gestión de errores se controla automáticamente por Java y para ello simplemente tenéis que introducir un par de líneas para que funcione. Y con algunas líneas más, podéis hacer un control exhaustivo añadiendo vuestros propios mensajes de error.

NOTA:

Por si no os gusta/os queda corta la explicación de la herencia, también podéis mirarlo en el apartado 6.4 de este material complementario.

Ya adelanto que este es un tema mucho más suave que el anterior.

Os deseo un buen estudio.

Laboratorio

El laboratorio se visualiza mejor en alta definición (HD) y a pantalla completa.

También tienes la posibilidad de ver el video con subtítulos. Para ello, haz clic sobre el botón “Turn on Captions” (CC).

Décima Práctica de Evaluación (PEV10)
Práctica de evaluación

La Décima Práctica de Evaluación del módulo es una práctica dividida en dos partes.

  1. La primera parte trata la herencia. Debéis crear dos nuevas clases que son heredadas (extienden) la clase Equipo. Estas clases tienen atributos propios y sobrecargan el método toString() para visualizar todos esos atributos.

  2. La segunda parte trata el manejo de excepciones. Simplemente debéis tratar los posibles errores para que aparezcan vuestros propios mensajes.

Recordad que para acceder a la evaluación cuatrimestral, la entrega de todas las PEVs es obligatoria (y cada una de ellas debe tener una nota superior a 2).

Sinopsis de la película "Echelon: la máquina espía"Documental

Mira el documental “Echelon: la máquina espía”. A continuación, comenta tus impresiones sobre lo que en él se dice en el foro del Aula Virtual.

Enlace al documental en Megavideo: http://www.megavideo.com/?v=CT2FXMDS

Orientaciones didácticas

Las orientaciones didácticas de una unidad son un resumen (no más de un folio) con unas pequeñas pautas  que permiten al alumno hacerse una idea general de qué va a aprender en esa unidad – respecto a los contenidos teóricos – y cómo debe desarrollar la parte práctica.

En estas orientaciones también se incluye un registro organizado con los comentarios realizados por el alumnado durante el desarrollo de la unidad, que seguramente ayudarán a facilitar la comprensión de los conceptos teórico-prácticos.

Aquí tenéis las orientaciones didácticas de la unidad 10:

Herencia en Java

Publicado: Sábado, 13 \13\UTC junio \13\UTC 2009 en 10. Programación orientada a objetos (y II)

Ahora que ya parece que estamos entendiendo la manera de trabajar con objetos, vamos a complicarnos un poco más (la verdad es que muy poco más).

¿Qué es la herencia?

Es un mecanismo que nos permite manejar clases que son muy parecidas a otras clases que ya existen, aunque difieren de estas en algunas características.

IMPORTANTEUn concepto extremadamente parecido lo habéis estudiado en el módulo de SGBD, en lo que allí se denomina especialización y generalización.

Se trata de un mecanismo que funciona como una estructura jerárquica, donde cada clase puede tener una única superclase (que se encuentra por encima de ella en la jerarquía) y una o varias subclases (que se encuentran por debajo en la jerarquía). Las clases que se encuentran por debajo se dice que heredan de las clases que se encuentran por encima.

Aquí tenéis un diagrama que muestra un ejemplo de jerarquía:

Ejemplo de herencia

En este diagrama:

  • La clase Empleado es la superclase de Director, Comercial e Informático.
  • Las clases Director, Comercial e Informático son subclases de la clase Empleado.
  • La clase Director es la superclase de Ejecutivo.
  • La clase Ejecutivo es la subclase de Director.

Las subclases heredan todos los métodos y atributos de sus superclases. Por tanto, al definir una subclase, esta tiene automáticamente el mismo comportamiento que la superclase que hereda. Y tened en cuenta que esta herencia sube en la jerarquía hasta llegar a la cumbre.

Existe una raíz en esta jerarquía, que es la clase Object. Todas las clases creadas heredan las características y el comportamiento de Object.

Ejemplo de herencia con Object

Si necesitamos añadir características y/o funcionalidades de una clase en otra clase, debemos crear una subclase. Como ya hemos comentado, esta subclase heredará todo el comportamiento de su superclase y nosotros simplemente deberemos añadir aquellos atributos y métodos específicos en la subclase que la diferencian de su superclase.

¿Cómo se define la herencia en Java?

Para indicar que una clase herada de otra, se utiliza la palabra reservada extends. Siguiendo el ejemplo de más arriba, deberíamos definir las clases de la siguiente manera:

class Empleado {}

class Director extends Empleado {}

class Comercial extends Empleado {}

class Informatico extends Empleado {}

class Ejecutivo extends Director {}

Como podéis observar, se define de manera totalmente natural a como se expresa en nuestro propio lenguaje.

Método constructor

Cuando se crea un objeto de una clase heredada, primero se llamará al constructor de su superclase y a continuación al constructor propio.

Continuando con el ejemplo de los empleados, si creamos un objeto Comercial:

Comercial unObjetoComercial = new Comercial();

En primer lugar se llamará al constructor de la clase Empleado y a continuación al constructor de la clase Comercial.

Podéis hacer una sencilla prueba de este comportamiento, creando un nuevo proyecto, llamado por ejemplo Herencia y dentro de este proyecto:

– Creáis una clase Empleado con el siguiente código:

public class Empleado {

public Empleado () {

System.out.println(“Empleado”);

}

}

– Creáis una clase Comercial con el siguiente código:

public class Comercial extends Empleado{

public Comercial () {

System.out.println(“Comercial”);

}

}

– Creáis una clase TestHerencia con el siguiente código:

public class TestHerencia {

public static void main(String[] args) {

Comercial unObjetoComercial = new Comercial();

}

}

Al ejecutar el código se puede comprobar cómo aparece primero el mensaje Empleado (se ha llamado al constructor Empleado()) y, a continuación, el mensaje Comercial (se ha llamado al constructor Comercial()).

Redefinición de funciones

En ocasiones, conviene tener métodos en las clases heredadas con la misma signatura (nombre de método y parámetros que admite). Por ejemplo, podría ser interesante tener un método llamado sueldo en cada una de las clases que tuviese código específico para controlar las bonificaciones específicas según el cargo del empleado en la empresa. Así, tendríamos algo parecido a esto:

_________________________________________________________

public class Empleado {

public Empleado () {

System.out.println(“Empleado”);

}

public void sueldo() {

System.out.println(“Sueldo base de un empleado”);

}

}

__________________________________________________________

Código de Empleado.java

__________________________________________________________

public class Comercial extends Empleado{

public Comercial () {

System.out.println(“Comercial”);

}

public void sueldo() {

System.out.println(“Sueldo base de un empleado+sueldo específico del cargo de comercial”);

}

}

__________________________________________________________

Código de Comercial.java

__________________________________________________________

public class TestHerencia {

public static void main(String[] args) {

Comercial unObjetoComercial = new Comercial();

unObjetoComercial.sueldo();

}

}

__________________________________________________________

Código de TestHerencia.java

Como es de esperar, al ejecutar el método sueldo() aparece el código de la clase Comercial. Lo que debemos tener en cuenta en este caso es que estamos ocultando el método de la superclase en la clase heredada.

Polimorfismo

Esta es la última herramienta que nos proporciona la herencia. Se trata de la capacidad que tiene un objeto de una superclase de convertirse en un objeto de cualquiera de sus subclases. Es decir, Java permite realizar intrucciones de este tipo:

Empleado unObjetoComercial = new Comercial();

unObjetoComercial está definida como un objeto de la clase Empleado, pero se le reserva espacio de memoria como un objeto de tipo Comercial. Esto es correcto (y ni en la compilación ni en la ejecución habrá errores) ya que la clase Comercial hereda de la clase Empleado.


Creative Commons License
Herencia en Java by Cristian Jorge Garcia Marcos is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 3.0 España License.

Excepciones en Java

Publicado: Sábado, 13 \13\UTC junio \13\UTC 2009 en 10. Programación orientada a objetos (y II)

Nos guste o nos deje de gustar, la realidad es que los programas no son perfectos y siempre acaban por funcionar de manera inadecuada, ya sea por errores de programación, errores en la entrada de datos de los usuarios, hardware que deja de responder, o cualquier otra cosa que pueda pasar. De esto es lo que vamos a hablar en esta entrada; en concreto, de cómo desarrollar nuestros programas para que gestionen correctamente los errores que puedan producirse.

Un poco de historia (o cómo funcionábamos en la era pre-POO)

La gestión de errores en lenguajes de programación tradicionales se ha hecho habitualmente mediante el uso de sentencias condicionales que trataban los distintos errores que el programador podía presuponer. Algo parecido a esto:

int status = miFuncionQueAcabaraConLaPobrezaEnElMundo();

if (status == 0) {

// La función se ejecuta correctamente, tenemos un mundo mejor. Creemos código ahora para abordar la paz mundial.

}

} else {

switch (status) {

case 1: System.out.println(“Error de tipo 1. Los gobiernos no ayudan.”);

case 2: System.out.println(“Error de tipo 2. La población no se implica.”);

case 3: System.out.println(“Error de tipo 3. Es una utopía”);

default: System.out.println(“Cualquier otro error que no había previsto”);

}

}

En este código se llama al método para “acabar con la pobreza en el mundo” que estará en algún otro lugar de la clase. Este método devuelve un entero que indica que se ha ejecutado correctamente (devuelve un 0) o bien ha ocurrido un error (devuelve cualquier otro valor diferente de 0). Según que error ocurra, el código mostrará un mensaje u otro.

Fijaos que la cantidad de código que controla los errores oscurece el código “normal”. A medida que el código aumente, también se hará más complicado el control de errores. Además, se dificultará la lectura del programa y su mantenimiento.

Con el lenguaje Java esta idea del control de errores deja de existir, ya que la gestión de errores se realiza automáticamente. Para hacer esta gestión automática, Java incluye un conjunto de clases creadas específicamente para el control de errores, que se llaman excepciones.

¿Cómo funcionan las excepciones?

Cuando un programa finaliza su ejecución de manera anormal, se lanza una excepción. Las excepciones pueden haberse lanzado por las clases que se utilizan o bien manualmente por tu propio código.

Además de “lanzadas” (del término thrown en inglés), las excepciones también se pueden “capturar” (del término catch en inglés). Capturar una excepción significa que tú mismo controlarás esa excepción para que el programa no finalice de manera inesperada.

Las excepciones son clases heredadas de la clase Throwable y pueden pertenecer a distintos paquetes. En todos los tipos se pueden usar los métodos siguientes:

  1. String getMessage(). Mensaje de la excepción
  2. String toString(). Mensaje que describe la excepción
  3. void printStackTrace(). Método desde el cual se lanzó la excepción

Capturar una excepción

Como ya hemos comentado, cuando en un método se produce una situación inesperada, se lanza una excepción. Para capturarla, se utilizan el conjunto de sentencias try, catch y finally.

Todo el código que pongamos dentro de un bloque try será inspeccionado automáticamente para controlar situaciones anómalas que, en caso de ocurrir, pasarían el control al bloque catch, encargado de gestionar el error producido. Para cada error que queramos controlar, deberemos incluir un nuevo bloque catch. Podemos incluir tantos bloques catch como consideremos oportunos. Sin embargo, el bloque finally es opcional y se ejecuta siempre, tanto si se produce excepción como si el código dentro del bloque try se ejecuta correctamente.

ATENCIÓNEl bloque finally se ejecutará incluso si existe una sentencia return en el bloque try.

Veamos la sintaxis para el control de errores mediante el uso de sentencias try-catch-finally.

try {

// Aquí va nuestro código de programa

} catch (excepcionACapturar e) {

// Aquí va el código que se ejecuta si se produce una excepción del tipo excepcionACapturar

} catch (Exception e) {

// Aquí va el código que se ejecuta si se produce cualquier otra excepción

} finally {

// Opcional. Aquí va el código que va a ejecutarse siempre, tanto si se produce excepción como si no se produce.

}

Crear una excepción definida por el usuario

Además de las excepciones que definen los métodos de las clases, también podemos definir nuestras propias excepciones.

Para crear este tipo de excepciones, heredamos de la clase Exception. Veamos un ejemplo:

public class miExcepcion extends Exception {

// Aquí se definen los atributos de la clase

public miExcepcion () {

// Método constructor

}

// Aquí se definen otros métodos, como por ejemplo, getters y setters

}

Para lanzar esta excepción, utilizamos la sentencia throw. Ejemplo:

throw new miExcepcion();

Esta instrucción lanza la excepción miExcepcion() que habíamos definido anteriormente.


Creative Commons License
Excepciones en Java by Cristian Jorge Garcia Marcos is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 3.0 España License.