- Introducción
El comportamiento de una clase se puede modificar y extender para crear nuevas clases a partir de clases ya existentes
A la clase original se le llama clase base o padre, mientras que a la que modifica y extiende las características se le llama clase heredada o hija. A este mecanismo se le conoce como el nombre de Herencia
En Java, existe una nueva construcción que permite especificar qué métodos debe implementar una clase. Esta nueva construcción se llama <<interface>>.
Además introduciremos las enumeraciones, nueva construcción en Java desde la versión 5.
Finalmente veremos como agrupar las clases que están lógicamente relacionadas a través de los paquetes.
- Herencia
- Sobrescritura de variables y métodos
- Sobrescritura de constructores
- Vinculación dinámica
- El operador instanceof
- Clases abstractas
- Interfaces
- Enumeraciones
- values(); que devuelve un array con los elementos de la enumeración.
- ordinal(); que nos devuelve el orden del elemento dentro del array, empezando desde 0.
- Paquetes
public class Punto3D extends Punto { //"Punto3D" se extiende a la clase "Punto"
protected float z; //Los nuevos atributos de la clase "Punto3D"
public Punto3D() {
super();
this.z = 0.0f;
}
public Punto3D(float x, float y) {
super(x, y);
this.z = 0.0f;
}
public Punto3D(Punto unPunto) {
super(unPunto.getX(), unPunto.getY());
this.z = 0.0f;
}
// Como vemos en los 3 métodos siempre utilizamos "super()" al principio.
public Punto3D(float x, float y, float z) {
super(x, y);
this.z = z;
}
public float getZ() { //Este método es nuevo
return z;
}
//El resto de métodos se han sobrescrito
public Punto inverso() {
return new Punto3D(-x, -y, -z);
}
public String toString() {
return "("+x+", "+y+", "+z+")";
}
public void print() {
System.out.println("Coordenadas del punto "+this);
}
A una variable referencia a una clase A, siempre que se le puede asignar un objeto de cualquier clase hija.
Al conrario nunca es posible y generará un error.
//En es te código no hay errores ¿Qué se imprime?
public class herenciaPunto3D {
public static void main(String args[]) {
Punto3D punto3D = new Punto3D(1.0f, 2.0f, 3.0f);
Punto punto = unPunto3D;
punto.print();
punto.inverso().print();
}
}
//Vinculación dinámica
Coordenadas del punto (1.0, 2.0, 3.0)
Coordenadas del punto (-1.0, -2.0, -3.0)
Punto punto = new Punto(1.0f, 2.0f);
Punto3D punto3D = unPunto;
//¿Es esto posible?

Los atributos y métodos de la clase padre siempre serán accesibles desde la hija a través de super.
class Entero {
public int dato;
public void metodo() {};
}
class Real extends Entero {
public float dato; //Sobrescribe a "dato" de la clase padre "Entero".
public void metodo() {}; //Sobrescribe a "metodo" de la clase padre "Entero".
}
//Error
public class A {
private int a;
public A(int a) {
this.a = a;
}
}
public class B extends A {
private int b;
public B(int b) {
this.b = b;
}
}
public static void main (String args[]) {
B b = new B(2);
}
public class A {
public A() {};
public void metodo() {
System.out.println("Clase A");
}
}
class B extends A {
public B() {};
public void metodo() {
System.out.println("Clase B");
}
}
public static void main(String args[]) {
System.out.println("Dame un numero:");
int entero = Teclado.leeEntero();
A a;
if(entero > 100) a = new A();
else a = new B();
a.metodo();
}
Como ya sabemos, a través de la herencia podemos utilizar referencias de una clase base sobre objetos de sus clases hijas, y al llamar a los métodos se vincularán los del objeto instanciado y no los que indique la referencia.
Con el operador instanceof, podemos saber el tipo de objeto a través de una referencia.
Este operador será de mucha utilidad cuando veamos las Colecciones
public static void main(String args[]) {
A a = new A();
B b = new B();
System.out.println("Es a instancia de A: "+(a instanceof A));
System.out.println("Es b instancia de B: "+(b instanceof B));
System.out.println("Es a instancia de B: "+(a instanceof B));
System.out.println("Es b instancia de A: "+(b instanceof A));
a = b;
System.out.println("-----------------");
System.out.println("Es a instancia de A: "+(a instanceof A));
System.out.println("Es b instancia de B: "+(b instanceof B));
System.out.println("Es a instancia de B: "+(a instanceof B));
System.out.println("Es b instancia de A: "+(b instanceof A));
}
public abstract class ClaseAbstracta {
int a;
public ClaseAbstracta() {};
public abstract void metodo(); //Un método abstracto no se define
public void noAbstracto() { // La clase puede tener otros métodos NO abstractos
System.out.println(“Hola”);
}
}
// No se pueden crear instancias de una clase abstracta
Como Java sólo permite herencia simple no podremos modelar el comportamiento de una clase mediante varias clases abstractas.
Para poder añadir varios "comportamientis" a nuestra clase lo haremos a través de interfaces.
Una clase sólo tiene una línea de herencia, pero puede implementar varios interfaces.
Los interfaces son una generalización de las clases abstractas.
interface SeDibuja {
static final Color rojo = Color.RED;
//No se implementa ningún método
void dibujate();
void ponColor(Color unColor);
Color dameColor();
}
public class PuntoVisible implements SeDibuja {
private Color color;
// La clase implementa el interface, debe definir el método dibujate()
public void dibujate() {
System.out.println("Se dibuja el punto");
}
}
public class CirculoVisible implements SeDibuja {
public void dibujate() {
System.out.println("Se dibuja el circulo");
}
}
// En el programa principal
PuntoVisible pv = new PuntoVisible();
CirculoVisible cv = new CirculoVisible();
SeDibuja spd = pv; //Utilizamos una referencia al interfaz
spd.dibujate();
spd = cv;
spd.dibujate();
Los interfaces también se pueden extender
interface Vehiculo {
public float getVelocidadMaxima();
}
interface Furgoneta extends Vehiculo { // <--- public float getCilindrada(); public int getPlazas; }
Incluso un interfaz puede extender más de un padre.
interface Vehiculo {
interface Vehiculo {
public float getVelocidadMaxima();
}
interface Imposiciones {
public float getImpuestoCirculacion();
}
interface Furgoneta extends Vehiculo, Imposiciones {
public float getCilindrada();
public int getPlazas;
}
Desde la Versión 5, se ha introducido en el lenguaje las enumeraciones
Las enumeraciones son tipos de datos que permiten ser enumerados (se les puede asignar valores enteros)
La definición de una enumeración es muy sencilla:
enum Semana {LUNES, MARTES, MIERCOLES,
JUEVES, VIERNES, SABADO, DOMINGO};
Semana dia = Semana.LUNES
Características:
Las enumeraciones extienden implicitamente a clase "java.lang.Enum", por lo que no pueden extender a ninguna otra clase
Sí que pueden implementar interfaces.
Pueden implementar métodos como cualquier otra clase.
No se pueden extender.
Poseen dos métodos interesantes:
Semana dia = Semana.LUNES;
System.out.println("Día: " + dia + " orden: " + dia.ordinal());
// Día: LUNES orden: 0
public enum Semana {
LUNES("Los lunes no me puedo levantar"),
MARTES("Ni te cases ni te embarques"),
MIERCOLES("Sin comentarios"),
JUEVES("Siempre en medio"),
VIERNES("Quedamos para salir"),
SABADO("Volvemos a quedar"),
DOMINGO("Mañana a clase de nuevo");
private String comentario;
// Constructor acceso de paquete o private.
Semana(String comentario) {
this.comentario = comentario;
}
public String getComentario() {
return comentario;
}
public static void main(String args[]) {
for(Semana dia: Semana.values())
System.out.println(dia + " : " +
dia.getComentario());
}
}
Los paquetes sirven para organizar jerárquicamente las clases
Una clase se asigna a un paquete con la siguiente línea antes de la definición de la clase:
package directorio.del.paquete;
public class A {//...
El fichero con los bytecodes de la clase A debe estar en un directorio directorio/del/paquete.
Otra clase, la importa de este modo:
import directorio.del.paquete.*;
| Puede acceder a...? | ||||
| misma clase | SI | SI | SI | SI |
| subclase del paquete | NO | SI | SI | SI |
| clase del paquete | NO | SI | NO | SI |
| Subclase otro paquete | NO | NO | SI | SI |
| clase otro paquete | NO | NO | NO | SI |
- Resumen
La herencia es el mecanismo utilizado en POO para crear nuevas clases a partir de clases ya existentes. En Java sólo existe herencia simple.
Las clases hijas añaden nuevos atributos y métodos. Asimismo, pueden “ocultar” o sobrescribir atributos y métodos de la clase base.
Una referencia a una clase base puede contener un objeto de cualquier clase hija, pero nunca al revés.
La sobrescritura se resuelve en tiempo de ejecución mediante vinculación dinámica.
Una clase base puede forzar que sus hijas definan algún método declarándolos como abstract. No se pueden crear instancias de una clase abstracta.
La generalización de las clases abstractas son los interface. Un interface es una plantilla, declara todos los métodos que una clase que implemente el interface debe definir. Una clase puede implementar cuantos interfaces haga falta.
Los paquetes son de utilidad para estructurar de un modo jerárquico las clase. Los paquetes imponen restricciones de acceso a sus clases.
No hay comentarios:
Publicar un comentario