Tabla de contenidos
El objetivo general de esta parte de la sesión es recordarte las cosas que deberías haber aprendido en el primer cuatrimestre, y proponerte algunos recursos y materiales con los que reforzar dichos conocimientos, si fuera necesario. Si tienes déficits considerables de esa parte, ten en cuenta que vas a necesitar más tiempo para conseguir estos objetivos que el estimado para la sesión.
Define, describe y programa correctamente las clases y objetos. (Bloom 3*)
Programa algoritmos sencillos usando bucles. (Bloom 3*)
Representa y procesa estructuras de datos sencillas mediante arrays. (Bloom 3*)
Define el concepto de herencia. (Bloom 1*)
Describe la sintaxis para usar herencia. (Bloom 1)
Dibuja los diagramas UML que representan la herencia. (Bloom 1*)
Explica cuáles son los miembros (atributos y métodos) de una clase (subclase) que se heredan de otra clase (superclase). (Bloom 2*)
Explica cómo construir jerarquías de clases. (Bloom 2*)
Dada una descripción textual, dibuja el diagrama de la correspondiente herarquía de clases. (Bloom 3)
Dada una jerarquía de clases, programa las clases participantes. (Bloom 3*)
Dado un conjunto de clases con dependencias de herencia, extrae la jerarquía de clases. (Bloom 3*)
Resuelve cuestiones teóricas relativas a la herencia. (Bloom 3*)
Dado un programa que use herencia, identifica los siguientes elementos: superclase, subclase, método sobreescrito, método sobrecargado. (Bloom 4)
Resuelve problemas que involucren el uso de herencia, partiendo de un diseño inicial de la solución que se proporcione con el enunciado y describa el sistema a modelar. (Bloom 5)
Define el concepto de sobreescritura de método. (Bloom 1*)
Define el concepto de polimorfismo. (Bloom 1*)
Explica cómo y cuándo se aplica la compatibilidad de tipos en una jerarquía de clases (hacia arriba y hacia abajo).
Explica cómo funciona la sobreescritura de métodos, es decir, cómo decide el sistema qué método incvocar en cada caso para un objeto particular. (Bloom 2*)
Da ejemplos de compatibilidad de tipos (hacia arriba y hacia abajo), y prográmalos en Java. (Bloom 3*)
Programa y prueba una jerarquía de clases con un ejemplo de sobreescritura de método. (Bloom 3*)
Dado un programa que use herencia y polimorfismo, identifica los siguientes elementos: superclase, subclase, método sobreescrito, método sobrecargado. polimorfismo, identifica dónde se está reutilizando código. (Bloom 4)
Define el concepto de método abstracto y de clase abstracta. (Bloom 1*)
Define el concepto de interfaces. (Bloom 1*)
Describe la sintaxis para declarar e implementar interfaces. (Bloom 1*)
Dibuja el diagrama UML para representar la implementación de interfaces. (Bloom 1*)
Explica por qué no es posible crear objetos de una clase abstracta. (Bloom 2*)
Explica la diferencia entre clase abstracta e interfaz. (Bloom 2*)
Explica por qué la herencia múltiple es problemática (y no está permitida en Java) mientras que la implementación múltiple de interfaces no es problemática y está permitida. (Bloom 2*)
Explica cuáles son las relaciones polimórficas dentro de una jerarquía de clases (usando herencia o interfaces). (Bloom 2*)
Pon un ejemplo de una clase con un método abstracto. (Bloom 3*)
Programa una clase que herede de una clase abstracta. (Bloom 3)
Programa una clase que implemente una interfaz. (Bloom 3*)
Programa una clase que implemente una interfaz y herede de otra clase. (Bloom 3*)
Resuelve cuestiones teóricas referentes a la implementación de interfaces. (Bloom 3*)
Dado un programa que use herencia y/o implementación de interfaces, identifica los siguientes elementos: superclase, subclase, interfaz, implementación de la interfaz, método sobreescrito, método sobrecargado. (Bloom 4)
Explica cómo usar la herencia de clases o la implementación de interfaces para representar el polimorfismo. (Bloom 4)
Resuelve problemas que involucren el uso de herencia y/o interfaces, partiendo de un diseño inicial de la solución que se proporcione con el enunciado y describa el sistema a modelar. (Bloom 5)
Como parte de su declaración e inicialización, hay que indicar
la dimensión de un array. Ésto constituye una de sus principales
ventajas/desventajas con respecto a otras estructuras como por
ejemplo las clases que implementan la interfaz List
o las listas enlazadas.
Es recomendable etiquetar los atributos de una clase como private
y acceder a ellos vía método.
El código siguiente es erróneo.
public boolean esCarnivoro (Animal animal){ boolean resultado; if (animal.estaClasificado()){ if (animal.getTipo().equals(Animal.CARNIVORO)){ resultado=true;} else{ if (animal.getTipo().equals(Animal.OMNIVORO)){ resultado=true;} else{resultado = false;}}} return resultado;}
El código siguiente es erróneo:
public boolean esCarnivoro (Animal animal){ try{ boolean resultado= false; if (animal.estaClasificado()){ if (animal.getTipo().equals(Animal.CARNIVORO)){ resultado = true;} else{ if (animal.getTipo().equals(Animal.OMNIVORO)){ resultado = true; } else{resultado = false;}}} } catch (AnimalException e){// Tratamiento excepción}} return resultado;}
Como parte de la implementación de herencia, el constructor de la clase hija (o derivada) realiza una llamada al constructor de la clase base y, por tanto, si no se emplea el constructor por defecto en la clase base, es necesario indicarlo explícitamente en la clase derivada.
La herencia guarda relación con una técnica de diseño denominada Diseño Incremental, que consiste en ir incorporando mayor funcionalidad poco a poco a un planteamiento de partida.
El método instanceOf
puede resultarte muy útil para
clasificar objetos en el ámbito de la herencia.
Las constantes en Java se definen con los identificadores
final
y static
.
Java permite métodos sobrecargados.
Dispones de la posibilidad de sobreescribir o sobrecargar un método en una clase derivada según tus necesidades.
Dos formas habituales de reutilizar objetos son herencia y composición.
Puedes identificar y diferenciar cuándo emplear herencia y cuándo composición a la hora de modelar una clase.
Herencia, abstracción y definición de interfaces son técnicas de implementación muy relacionadas con el diseño conceptual.
Una clase abstracta puede poseer atributos, pero estos por definición
deben ser etiquetados como static
con los riesgos que esto
conlleva.
El empleo de interfaces es una herramienta muy útil en el diseño modular y simplifica enormemente el trabajo en equipo.
El siguiente código es correcto:
interface dispositivoLecturaFichero{ String lecturaSigLinea (String rutaFichero); List<String> leerSigParrafo(String rutaF); } public abstract class LectorFichero implements dispositivoLecturaFichero{ String lecturaSigLinea (String rutaFichero) {...} abstract List<String> leerSigParrafo(String rutaF); }
Dedicar un tiempo razonable a modelar, definir y detectar las peculiaridades del programa a implementar, así como adelantar los posibles problemas que puedan presentarse, constituye una buena práctica que entre otras cosas te ahorrará tiempo y dotará a tus programas de flexibilidad y trazabilidad.
El siguiente código es erróneo:
interface lectorFichero{ String leerSigLinea (String ruta); List<String> leerSigBloque(String ruta);} interface lectorMedia{ FicheroMultimedia leerSig(String ruta);} class lector implements lectorFichero,lectorMedia{ String leerSigLinea (String ruta){ <código específico>} List<String> leerSigBloque(String ruta){ <código específico>} FicheroMultimedia leerSigBloque(String ruta){ <código específico>}}
El siguiente código es erróneo:
boolean encontrado = false; int i=0; int conectadosPractica = 0; while (i<asignaturas.length)){ if (asignaturasUsuarios[i].equals(buscada)==0){ conectadosPractica = conectadosPractica + 1;} else{ i=i+1;} } return encontrado;
En el siguiente fragmento de código, para valor = 6
,
el resultado no es el deseable.
boolean multiplo2 = false; boolean multiplo3= false; if (valor%2==0){ multiplo2=true; } else{ if (valor%3==0){ multiplo3=true; } }