Sunteți pe pagina 1din 79

Programacin Orientada a Objetos

MCA Gustavo Alejandro Galindo Rosales Marzo 2013 igusi_soft@hotmail.com


1

Herencia

Definicin: clase base, clase derivada.


La herencia es una propiedad esencial de la Programacin Orientada a Objetos que consiste en la creacin de nuevas clases a partir de otras ya existentes.

El lenguaje Java permite heredar a las clases caractersticas y conductas de una o varias clases denominadas clase base. Las clases que heredan de clases base se denominan clases derivadas, estas a su vez pueden ser clases bases para otras clases derivadas. Se establece as una clasificacin jerrquica, similar a la existente en Biologa con los animales y las plantas.

La herencia ofrece una ventaja importante, permite la reutilizacin del cdigo. Una vez que una clase ha sido depurada y probada, el cdigo fuente de dicha clase no necesita modificarse. Cuando una clase deriva de otra, se llama superclase a la clase base de la que deriva la nueva clase. La clase derivada o subclase hereda todos los atributos y mtodos de su superclase. Para indicar que la clase B (clase descendiente, derivada, hija o subclase) hereda de la clase A (clase ascendiente, padre, base o superclase) se emplea la palabra reservada extends en la cabecera de la declaracin de la clase descendiente. La sintaxis es la siguiente:

public class ClaseB extends ClaseA { // Declaracin de atributos y mtodos especficos de la // ClaseB y/o re declaracin de componentes heredados } Diagrama de clase Herencia Clase A

Clase base

Clase B

Clase derivada

Herencia simple, herencia mltiple.


Existen dos tipos de herencia: sencilla y mltiple. Sencilla significa que slo heredamos de una clase base, mientras que mltiple indica que tenemos varias clases base (por ejemplo un hidroavin hereda de barco y de avin). Java slo soporta herencia simple. Herencia simple. En orientacin a objetos la herencia es el mecanismo fundamental para implementar la reutilizacin y extensibilidad del software. La herencia facilita la creacin de objetos a partir de otros ya existentes, obteniendo caractersticas (mtodos y atributos) similares a los ya existentes.

Ejemplos:

Supongamos que tenemos una clase Precio que describe la conducta del costo de un producto y a partir de esta se construye la clase Producto que hereda de la clase Precio.
package almacen;
public class Precio { // Atributos protected double costo; // Mtodos public double getCosto(){ return costo; } public void setCosto(double x) { costo = x; } }

Se construye la clase Producto como descendiente de la clase Precio de la siguiente forma:


package almacen;
public class Producto extends Precio { // Atributos protected int codigo; // Mtodos public int getCodigo() { return codigo; } public void setCodigo(int x) { codigo = x; } public void asignaProducto(int cod, double p) { setCodigo(cod); setCosto(p); }

public String toString() { return "Cdigo: " + codigo + "\nPrecio: $ " + costo + " pesos"; } }

Se construye la clase Almacen de la siguiente forma:


package almacen; public class Almacen { public static void main (String [] args){ Producto p = new Producto(); p.asignaProducto(200201,15.8); Producto q = new Producto(); q.setCodigo(200202); q.setCosto(34.3); System.out.println(p.toString()); System.out.println(q.toString()); } }

Durante la ejecucin del cdigo anterior, se generan las instancias referenciadas por p y q, cada una de las cuales est compuesta por dos atributos: costo, variable de instancia heredada de la clase Precio y cdigo, variable de instancia especfica de la clase Producto. Representacin grfica en memoria de las instancias de la clase Producto.

Construir una clase Factura descendiente de la clase Producto y que incluya dos atributos especficos llamados emisor y cliente y un mtodo llamado imprimirFactura.
package factura; public class Producto{ // Atributos protected int idProd; protected String descProd; protected double costo; // Mtodos public int getIdProducto(){ return idProd; } public String getDescripcion(){ return descProd; }

public double getCosto(){ return costo; } public void setIdProducto(int id){ idProd = id; } public void setDescripcion(String nomProd){ descProd = nomProd; } public void setCosto(double costProd){ costo = costProd; } }

package factura; public class Factura extends Producto{ // Atributos private String cliente; private final String emisor = "Almacenes No hay S.A. de C.V."; // Mtodos public void setCliente(String nCliente){ cliente = nCliente; } public void setDatosFactura(String nCliente, int idPto, String nProd, double cProd){ setCliente(nCliente); setIdProducto(idPto); setDescripcion(nProd); setCosto(cProd); }

public String imprimirFactura () { return "Emisor: " + emisor + "\nCliente: " + cliente + "\nId producto: " + idProd + "\nDescripcin: " + descProd + "\nCosto: $ " + costo + " pesos\n"; } } Se implementa la clase DemoFactura para probar la herencia package factura; public class DemoFactura { public static void main(String[] args) { // Declaracin de objetos de tipo Factura Factura objFact = new Factura(); Factura objFact1 = new Factura(); // Asignacin de datos al objeto objFact por medio del // mtodo setDatosFactura()

objFact.setDatosFactura("Juan Solano", 12, "Computadora Compaq", 12345.67); // Asignacin de datos al objeto objFact1 por medio de los // mtodos sets() objFact1.setCliente("Grady Booch"); objFact1.setIdProducto(3456); objFact1.setDescripcion("Monitor Acer 20 pulgadas"); objFact1.setCosto(2341.45); // Llamado al mtodo imprimirFactura() a travs de los // objetos objFact y objFact1 System.out.println(objFact1.imprimirFactura()); System.out.println(objFact.imprimirFactura()); } }

Construir las clases mamfero, gato y perro, haciendo que gato y perro hereden de mamfero y a travs de ellos se nombre al animal; pero as tambin se acceda al atributo patas dndole el valor por defecto para esa especie. package animales; import javax.swing.*; public class Mamifero{ // Atributos private int patas; private String nombre; // Constructor public Mamifero(String nombre, int patas){ this.nombre = nombre; this.patas = patas; }

// Mtodos public void imprimirPatas(){ JOptionPane.showMessageDialog(null, "Tiene " + patas + " patas", "Informacin",JOptionPane.INFORMATION_MESSAGE); } public void imprimirNombre(){ JOptionPane.showMessageDialog(null, "Nombre: " + nombre , "Informacin", JOptionPane.INFORMATION_MESSAGE); } public void imprimirDatos(){ JOptionPane.showMessageDialog(null, "Nombre: " + nombre + " es un mamfero y tiene " + patas + " patas", "Informacin", JOptionPane.INFORMATION_MESSAGE); } }

package animales; public class Perro extends Mamifero { public Perro(String nombre){ super(nombre, 4); } }

package animales; public class Gato extends Mamifero { public Gato(String nombre){ super(nombre, 4); } }

Nota: Solo recuerda que la palabra reservada super sirve para indicar que un atributo o un mtodo es de la superclase, es por ello que empleamos super para referenciar al constructor de la clase base.

package animales; public class Animal { public static void main(String [] args) { // Declaracin de los objetos Perro dog = new Perro("Candy"); Gato cat = new Gato("Rayita"); // Mtodos llamados a travs de los objetos dog y cat dog.imprimirPatas(); dog.imprimirNombre(); cat.imprimirNombre(); cat.imprimirPatas(); dog.imprimirDatos(); } }

20

A continuacin se presenta un ejemplo, donde al heredar de una clase base, heredaremos tanto los atributos como los mtodos, mientras que los constructores de la clase base son utilizados, pero no heredados. Construir las clases Persona y Taxista, haciendo que Taxista herede de la clase Persona y utilizando los constructores de la clase Persona para asignar datos a los atributos. package personas; public class Persona { // Atributos private String nombre; private int edad; // Constructores

public Persona(){ edad = 0; nombre = ""; } public Persona(String nombre){ edad = 0; this.nombre = nombre; } public Persona(String nombre, int edad){ this.edad = edad; this.nombre = nombre; } // Mtodos public int getEdad(){ return edad; }

public void setEdad(int edad) { this.edad = edad; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } } package personas; public class Taxista extends Persona { private int nLicencia; public void setLicencia(int num){ nLicencia = num; }

public int getLicencia() { return nLicencia; } } package personas; public class DemoTaxista { public static void main (String arg[]){ Taxista objTax = new Taxista(); objTax.setNombre("Luis"); objTax.setEdad(50); System.out.println("Nombre: " + objTax.getNombre()); System.out.println("Edad: " + objTax.getEdad()); } }

Ahora hagamos uso del constructor que existe en la clase Persona que recibe como parmetro el nombre de la persona, usndolo para la clase Taxista. Para ello modifiquemos el cdigo de la clase DemoTaxista: public class DemoTaxista { public static void main (String arg[]){ Taxista objTax = new Taxista("Jose"); objTax.setEdad(50); System.out.println(objTax.getNombre()); System.out.println(objTax.getEdad()); System.out.println(objTax.getLicencia()); } } Al compilar esta clase, se genera un error de compilacin, debido a que los constructores no se heredan, sino que hay que definir nuestros propios constructores en las clases base. El error mostrado es:

I:\personas\DemoTaxista.java:5: cannot find symbol symbol : constructor Taxista(java.lang.String) location: class personas.Taxista Taxista objTax = new Taxista("Jose"); ^ 1 error Para corregir el error, agreguemos en la clase Taxista los siguientes constructores: public Taxista(int licencia) { super(); nLicencia = licencia; } public Taxista(String nombre) { super(nombre); nLicencia = 0; }

public Taxista(String nombre, int edad) { super(nombre, edad); nLicencia = 0; } public Taxista(String nombre, int edad, int licencia) { super(nombre, edad); nLicencia = licencia; }

Ahora si podremos compilar y ejecutar la clase DemoTaxista. La llamada al mtodo super indica que estamos llamando a un constructor de la clase base, pensemos que un Taxista antes que ser Taxista es una Persona y por tanto tiene sentido llamar al constructor de la clase Persona antes que al de la clase Taxista.
Adems gracias al nmero de parmetros, al realizar la llamada a super podemos especificar cul de los constructores de la clase base queremos llamar.

Ahora agreguemos el mtodo getNombre() dentro de la clase Taxista, es decir, tenemos el mismo mtodo en la clase Persona y en la clase Taxista: public String getNombre() { return "Soy un taxista y me llamo: " + super.getNombre(); } Compilamos la clase Taxista y ejecutamos DemoTaxista. Veremos que el mensaje que aparece en pantalla demuestra que el mtodo getNombre() llamado es el del tipo real del objeto construido, en este caso el de la clase derivada que es Taxista. Tambin se aprecia que para acceder al atributo nombre es necesario acceder al mtodo getNombre() de la clase base y por ello empleamos la palabra reservada super.

Herencia mltiple.
La herencia mltiple en java no es soportada nativamente. Sin embargo muchos autores y desarrolladores la simulan utilizando la palabra reservada implements e interface, que sirven para implementar o cubrir una clase con respecto a otra. Ejemplos: Elaborar las clases necesarias para codificar el caso de una aplicacin universitaria. En ella sern docentes los alumnos y los profesores, pero no los administrativos (ni otros empleados). Los docentes se distinguen de otras personas en que tendrn un grupo y horario. Para ello se va a definir una interfaz de nombre Docente con las operaciones: setGrupo(), getGrupo() y getHorario(). Para los no docentes estas operaciones no tienen sentido. Sin embargo, si es cierto que todos los Alumnos, Profesores, Administrativos, etc., son Personas (es decir se pueden crear como derivadas de la clase Persona).

Diagrama de clases: Aplicacin universitaria

Docente

Archivo: Turno.java package universitaria;

public enum Turno {MATUTINO, VESPERTINO}

Archivo: Persona.java package universitaria; public class Persona { // Atributos private String nombre; private int edad; // Constructores public Persona(){ edad = 0; nombre = ""; }

public Persona(String nombre){ edad = 0; this.nombre = nombre; } public Persona(String nombre, int edad){ this.edad = edad; this.nombre = nombre; }

// Mtodos public int getEdad(){ return edad; } public void setEdad(int edad) { this.edad = edad; }

public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; }

public String toString(){ return "Nombre: " + nombre + "\nEdad: " + edad; }
}

Archivo: Docente.java package universitaria;

public interface Docente { void setGrupo(String grupo); String getGrupo(); Turno getTurno(); }
Archivo: Alumno.java package universitaria; public class Alumno extends Persona implements Docente{ // Atributos private String grupo; private Turno turno;

// Mtodos public Alumno(String nombre, int edad, String grupo, Turno turno){ super(nombre, edad); this.grupo = grupo; this.turno = turno; }
public void setGrupo(String grupo){ this.grupo = grupo; } public String getGrupo(){ return grupo; } public Turno getTurno(){ return turno; }

public String toString(){ return super.toString() + "\nGrupo: " + grupo + "\nTurno: " + turno + "\n"; } } Archivo: Empleado.java package universitaria; public class Empleado extends Persona{ // Atributos private int numEmpleado; private double sueldo; public Turno turno;

// Constructor public Empleado(String nombre, int edad, int numEmpleado, double sueldo, Turno turno){ super(nombre, edad);

this.numEmpleado = numEmpleado; this.sueldo = sueldo; this.turno = turno; } // Mtodos public int getNumEmpleado(){ return numEmpleado; } public double getSueldo(){ return sueldo; } public String toString(){ return super.toString() + "\nNum. de empleado: " + numEmpleado + "\nSueldo: $ " + sueldo + "\nTurno: " + turno; } }

Archivo: Profesor.java

package universitaria;
public class Profesor extends Empleado implements Docente{ // Atributos private String grupo; // Constructor public Profesor(String nombre, int edad, int numEmpleado, double sueldo, String grupo, Turno turno) { super(nombre, edad, numEmpleado, sueldo, turno); this.grupo = grupo; } // Mtodos public void setGrupo(String grupo){ this.grupo = grupo; }

public String getGrupo(){ return grupo; }


public Turno getTurno(){ return turno; } public String toString(){ return super.toString() + "\nGrupo: " + grupo + "\n"; } }

Archivo: Administrativo.java

package universitaria;
public class Administrativo extends Empleado{ // Atributos private String funcion; private String departamento; // Constructor public Administrativo(String nombre, int edad, int numEmpleado, double sueldo,Turno turno, String funcion, String departamento) { super(nombre, edad, numEmpleado, sueldo, turno); this.funcion = funcion; this.departamento = departamento; } // Mtodos public void setFuncion(String funcion){ this.funcion = funcion; }

public String getFuncion(){ return funcion; } public void setDepartamento(){ this.departamento = departamento; }
public String getDepartamento(String departamento){ return departamento; } public String toString(){ return super.toString() + "\nDepartamento: " + departamento + "\nFuncin: + funcion + "\n"; } }

Archivo: Universidad.java package universitaria; public class Universidad { public static void main(String[] args) { Alumno objAlumno = new Alumno("Carlos Alberto", 19, "D - 1", Turno.MATUTINO); System.out.println("Alumno:"); System.out.println(objAlumno.toString()); Profesor objProf = new Profesor("Jos Alberto", 45, 128, 8754.78, "D - 2", Turno.MATUTINO); System.out.println("Profesor:"); System.out.println(objProf.toString()); // Modificando el grupo del profesor System.out.println("Profesor con grupo modificado:"); objProf.setGrupo("F - 5"); System.out.println(objProf.toString()); Administrativo objAdmvo = new Administrativo("Mara", 32,120, 6578.98, Turno.MATUTINO, "Jefe de departamento", "Recursos humanos"); System.out.println("Administrativo:"); System.out.println(objAdmvo.toString()); } }

Elabore las clases necesarias simulando herencia mltiple para una biblioteca que contenga libros y revistas.

Las caractersticas comunes que se almacenan tanto para las revistas como para los libros son el cdigo, ttulo y el ao de publicacin. Estas tres caractersticas se pasan por parmetros en el momento de crear los objetos. Los libros tienen adems un atributo prestado. Los libros cuando se crean no estn prestados. Las revistas tienen un nmero total de revistas. En el momento de crear las revistas se pasa el nmero por parmetro. Tanto las revistas como los libros deben tener (aparte de los constructores) un mtodo toString() que devuelve el valor de todos los atributos en una cadena de caracteres. Tambin tienen un mtodo que devuelve el ao de publicacin y otro para el cdigo. Para prevenir posibles cambios en el programa se tiene que implementar una interfaz, Prstamo con los mtodos prestar(), devolver() y prestado(). La clase Libro implementa esta interfaz.

Diagrama de clases: Aplicacin biblioteca


<< interface>> Prstamo

Publicacin

Revista

Libro

Archivo: Publicacion.java package biblioteca; public class Publicacion{ // Atributos private String codigo; private String titulo; private int ao;

// Constructor public Publicacion(String codigo, String titulo, int ao){ this.codigo = codigo; this.titulo = titulo; this. ao = ao; }

// Mtodos public int getAo(){ return ao; } public String getCodigo(){ return codigo; } public String toString(){ return "Cdigo: " + codigo + "\nTitulo: " + titulo + "\nAo de publicacin: " + ao + "\n"; } }

Archivo: Prestamo.java package biblioteca;

public interface Prestamo{ void prestar(); void devolver(); boolean prestado(); }

Archivo: Revista.java package biblioteca; public class Revista extends Publicacion{ // Atributos private int numTotal;

// Constructor public Revista(String codigo, String titulo, int ao, int numTotal){ super(codigo, titulo, ao); this.numTotal = numTotal; }

// Mtodo public String toString(){ return super.toString() + "Numero: " + numTotal +"\n"; } }

Archivo: Libro.java package biblioteca;

public class Libro extends Publicacion implements Prestamo{ // Atributos private boolean prestado; // Constructor public Libro(String codigo, String titulo, int ao){ super(codigo, titulo, ao); prestado = false; }
// Mtodos public void prestar(){ prestado = true; }

public void devolver(){ prestado = false; } public boolean prestado(){ return prestado; }

public String toString(){ if(prestado()) return super.toString() + "Estado del libro: prestado" + "\n"; else return super.toString() + "Estado del libro: no prestado" + "\n"; } }

Archivo: Biblioteca.java package biblioteca;

public class Biblioteca { public static void main(String[] args) { Libro objLibro = new Libro("1020-L", "Herencia mltiple en Java", 2011 ); Revista objRevista = new Revista("1111-R", "Java total", 2011, 12); System.out.println("Libros:"); System.out.println(objLibro.toString()); System.out.println("Revistas:"); System.out.println(objRevista.toString()); } }

3.3 Reutilizacin de miembros heredados.


Una subclase puede acceder directamente a un atributo pblico, protegido, o predeterminado en su caso de su superclase. Si se define en la subclase uno de estos atributos, con el mismo nombre que tiene en la superclase; se oculta la definicin del mismo en la superclase. Por ejemplo, supongamos que una Clase Base define un atributo identificado por atribClase, que despus redefinimos en una SubClase: package reutilizacion; public class ClaseBase{ public int atribClase = 1; // Declaracin del atributo // Mtodos public int metodo1ClaseBase(){ return atribClase * 10; }

public int metodo2ClaseBase(){ return atribClase + 100; } }

package reutilizacion; public class SubClase extends ClaseBase{ // Atributos protected int atribClase = 2; // Redefinicin del atributo // Mtodos public int metodo1ClaseBase (){ return atribClase * - 10; } }

Ahora, la definicin del atributo atribClase en la subclase oculta la definicin del atributo con el mismo nombre en la superclase. Por lo tanto, la ltima lnea de cdigo del ejemplo siguiente devolver el valor de atribClase de SubClase. Si este atributo no hubiera sido definido en la subclase, entonces el valor devuelto sera el valor de atribClase de la superclase.
package reutilizacion;

public class Test{ public static void main(String[] args){ SubClase objSubClase = new SubClase(); System.out.println(objSubClase.atribClase); System.out.println(objSubClase.metodo2ClaseBase()); System.out.println(objSubClase.metodo1ClaseBase()); } }

Ahora, si el mtodo referenciado por el metodo1ClaseBase de la SubClase tuviera que acceder obligatoriamente al dato atribClase de la superclase. La solucin es utilizar para ese atributo nombres diferentes en la superclase y en la subclase. No obstante, aun habiendo utilizado el mismo nombre, se tiene otra alternativa de acceso: utilizar la palabra reservada super.

Por ejemplo:
public int metodo1ClaseBase (){ return super.atribClase * -10; } En cambio, la expresin siguiente hace referencia al dato atribClase de la superclase: ((ClaseBase)this).atribClase;

Por ejemplo: public int metodo1ClaseBase (){ return ((ClaseBase)this).atribClase; }

Nota: la tcnica de realizar una conversin explicita u obligada es la que tendremos que utilizar si necesitamos referirnos a un miembro oculto perteneciente a una clase por encima de la superclase.

3.4 Referencia al objeto de la clase base.

La funcionalidad de una clase existente se puede extender al crear una nueva clase que se deriva de ella. La clase derivada hereda las propiedades de la clase base y es posible agregar o remplazar mtodos y propiedades segn sea necesario.
El cdigo siguiente define una clase denominada Coordenada con dos atributos privados x e y que representan la posicin del punto en el plano cartesiano.

package coordenada;
public class Coordenada{ private int x, y; // Atributos

public Coordenada(){ // Constructor x = 0; y = 0;


}

// Mtodos public int getX(){ return x; } public void setX(int x){ this.x = x; } public int getY(){ return y; }

public void setY(int y){ this.y = y; }


}

package coordenada; import java.awt.Color;

public class FijarColor extends Coordenada{ private Color color; // Atributos public FijarColor(){ // Constructor this.color = Color.black; }
// Mtodos public Color getColor(){ return color; } public void setColor(Color color){ this.color = color; } }

Como en Java, no se puede utilizar una referencia a una clase base para tener acceso a los miembros y mtodos de una clase derivada, aunque la referencia de la clase base pueda contener una referencia vlida a un objeto del tipo derivado. Implcitamente, se puede hacer referencia a una clase derivada con una referencia al tipo derivado:

package coordenada;
public class DemoCoord { public static void main(String[] args) { FijarColor objColor = new FijarColor(); Coordenada coords = objColor; System.out.println("El valor de la referencia del objeto color es: " + objColor); System.out.println("El valor de la referencia del objeto coords es: " + coords); } }

En el cdigo de la aplicacin anterior, la referencia de la clase base, coords, contiene una copia de la referencia de la subclase objColor. Se puede tener acceso a los miembros de la clase base en una subclase incluso cuando los miembros de la clase base se remplazan en la superclase utilizando la palabra reservada super(). Por ejemplo, supongamos que la clase base Coordenada tuviera un mtodo denominado invertirCoordenada() que intercambia las coordenadas x e y. Se podra proporcionar un sustituto para este mtodo en la clase derivada FijarColor con un cdigo como ste: public void invertirCoordenada(){ int temp = super.getX(); super.setX(super.getY()); super.setY(temp); color = Color.GRAY; }

Como se puede observar, este mtodo intercambia x e y, luego establece el color del punto en gris. Se podra proporcionar acceso a la implementacin de la clase base para este mtodo creando otro mtodo en FijarColor, como el siguiente:

public void invertirCoordBase(){ super.invertirCoordenada(); } A continuacin, se invoca la palabra reservada super() en un objeto FijarColor mediante una llamada al mtodo invertirCoordBase().

package coordenada; public class DemoCoord1{ public static void main(String[] args) { FijarColor objFijarColor = new FijarColor(); // Estableciendo valores a las coordenadas x, y objFijarColor.setX(5); objFijarColor.setY(3); System.out.println("Los valores actuales de los atributos son:"); System.out.println("\t- x: " + objFijarColor.getX()); System.out.println("\t- y: " + objFijarColor.getY()); System.out.println("\t- color:" + objFijarColor.getColor()); System.out.println("Los valores de los atributos despus de llamar al mtodo invertirCoordBase()"); objFijarColor.invertirCoordBase();// llamando al mtodo base System.out.println("\t- x: " + objFijarColor.getX()); System.out.println("\t- y: " + objFijarColor.getY()); System.out.println("\t- color:" + objFijarColor.getColor());

System.out.println("Los valores de los atributos despus de llamar al mtodo invertirCoordenada()"); objFijarColor.invertirCoordenada(); // Llamando al mtodo derivado System.out.println("\t- x: " + objFijarColor.getX()); System.out.println("\t- y: " + objFijarColor.getY()); System.out.println("\t- color:" + objFijarColor.getColor()); }

Recuerde que se obtendra el mismo efecto si se asignara una referencia de la clase base a una instancia de FijarColor y, a continuacin, se tuviera acceso a sus mtodos. Por ejemplo:

package coordenada; public class DemoCoord2{ public static void main(String[] args) { FijarColor objFijarColor = new FijarColor(); Coordenada objCoord = objFijarColor; // Estableciendo valores a las coordenadas x, y objCoord.setX(5); objCoord.setY(3); System.out.println("Los valores actuales de los atributos son:"); System.out.println("\t- x: " + objCoord.getX()); System.out.println("\t- y: " + objCoord.getY()); System.out.println("\t- color:" + objFijarColor.getColor()); System.out.println("Los valores de los atributos despus de llamar " + "al mtodo invertirCoordenada()"); objCoord.invertirCoordenada(); System.out.println("\t- x: " + objFijarColor.getX()); System.out.println("\t- y: " + objFijarColor.getY()); System.out.println("\t- color:" + objFijarColor.getColor()); } }

3.5 Constructores y destructores en clases derivadas. Constructores en clases derivadas.

Al instanciar objetos de clases derivadas se inicia una cadena de invocaciones a constructores en las cuales el constructor de la clase derivada, antes de realizar sus propias tareas, invoca (ya sea implcita o explcitamente) al constructor de su clase base. Similarmente, si la clase base fue derivada de otra clase, el constructor de la clase base debe invocar al constructor de la clase ubicada en el siguiente nivel superior de la jerarqua, y as sucesivamente. El ltimo constructor invocado en la cadena es el constructor de la clase Object, cuyo cuerpo se ejecuta primero. El cuerpo del constructor de la clase derivada se ejecuta al final.
El constructor de cada clase base inicializa las variables de instancia que el objeto de la clase derivada hereda.

Destructores en clases derivadas.


Cuando se remueve de la memoria un objeto de una clase derivada, el recolector de basura invoca al destructor del objeto. Esto inicia una cadena de invocaciones a destructores, en donde el destructor de la clase derivada y los destructores de las clases bases directas e indirectas se ejecutan en orden inverso al que se ejecutaron los constructores, esto es, primero se ejecuta el destructor de la clase derivada y al final se ejecuta el destructor de la clase base ubicada en el nivel superior de la jerarqua. La ejecucin de los destructores debe liberar todos los recursos que el objeto adquiri, antes de que el recolector de basura reclame la memoria de ese objeto. Cuando el recolector de basura invoca al destructor de un objeto de una clase derivada, ese destructor realiza su tarea y despus invoca al destructor de la clase base. El proceso se repite hasta que se invoca al destructor de la clase Object.

Por ejemplo, el constructor de una clase derivada puede llamar al constructor de su clase base mediante la palabra super SubClase(lista_parmetros){ super(lista_parmetros); // sentencias adicionales } Si no se llama explcitamente al constructor de la clase base, se llama automticamente al constructor por defecto de la clase base class Rectangulo{ public int alto, ancho; Rectangulo(int alto,int ancho){ this.alto = alto; this.ancho = ancho; } }

class Cuadrado extends Rectangulo{ Cuadrado(int tam){ super(tam, tam); } }

3.6 Redefinicin de mtodos en clases derivada. En la clase derivada se puede redefinir algn mtodo ya definido en la clase base. Para redefinir un mtodo en la subclase, basta con declarar un mtodo con el mismo nombre. Si en una clase en particular se invoca a un mtodo, y el mtodo no est definido en la misma, es buscado automticamente en las clases superiores. Sin embargo, si existieran dos mtodos con el mismo nombre y distinto cdigo, uno en la clase y otro en una superclase, se ejecutara el de la clase, no el de la superclase. Al utilizar la herencia aparecen dos conceptos: super y this, this representa al objeto completo, en cambio super, slo representa la parte heredada de la clase base.

Cuando se hereda nos encontramos frente a un pequeo problema:

Qu sucede cuando se hereda un mtodo de la clase base, el cual estamos redefiniendo en la clase derivada?
Esto es un caso de sobre escritura de mtodos. La solucin es simple, cuando estemos ejecutando el mtodo de un objeto derivado se llamar al mtodo de su propia clase, es decir el redefinido. Si lo que se quiere es emplear el mtodo de la clase base, hay que emplear una tcnica que consiste en usar: super.mtodo(). Los constructores no son heredados, pero s llamados. Es decir, cuando se construye un objeto de la clase derivada se llama al constructor de la clase derivada, pero antes de comenzar a ejecutarse se llama al constructor de la clase base, que tras ejecutarse continua la ejecucin del constructor de la clase derivada.

Se puede elegir qu constructor de la clase base es llamado, generalmente llamando al mtodo super(), que representa al constructor de la clase base, pero al pasar parmetros distintos, seleccionamos qu constructor de la clase base queremos llamar. Por lo general, siempre se puede acceder explcitamente al mtodo de la clase superior mediante la instruccin super(). La funcionalidad de una clase existente se puede extender al crear una nueva clase que se deriva de ella. La clase derivada hereda las propiedades de la clase base y es posible agregar o remplazar mtodos y propiedades segn sea necesario. Por ejemplo: supongamos que tenemos una clase que describe la conducta de una ventana muy simple en Windows, aquella que no dispone de ttulo en la parte superior, por tanto no puede desplazarse, pero si cambiar de tamao modificando los valores de los bordes derecho e inferior.

La clase Ventana tendr los siguientes atributos: la posicin posX y posY de la ventana, de su esquina superior izquierda y las dimensiones de la ventana: ancho y alto. package windows; public class Ventana { // Atributos protected int posX, posY; protected int ancho, alto; // Constructor public Ventana(int posX, int posY, int ancho, int alto) { this.posX = posX; this.posY = posY; this.ancho = ancho; this.alto = alto; }

// Mtodos public void mostrar(){ System.out.println("posicin : posX = " + posX + ", posY = " + posY); System.out.println("dimensiones : ancho = " + ancho + ", alto = " + alto); } public void cambiarDimensiones(int ancho, int alto){ this.ancho = ancho; this.alto = alto; } } Adems del constructor de la clase, los mtodos: mostrar() que simula una ventana en un entorno grfico, solamente nos muestra la posicin y las dimensiones de la ventana y el mtodo cambiarDimensiones() que simula el cambio en el ancho y alto de la ventana.

Como vemos en el cdigo, el constructor de la clase base inicializa los cuatro atributos. Llamando al constructor y creando un objeto de la clase Ventana. Ventana objVentana = new Ventana(0, 0, 20, 30); Desde el objeto objVentana podemos llamar a los mtodos: objVentana.mostrar(); objVentana.cambiarDimensiones(10, 10); objVentana.mostrar(); Incrementamos la funcionalidad de la clase Ventana definiendo una clase derivada denominada VentanaTitulo. Los objetos de dicha clase tendrn todas las caractersticas de los objetos de la clase base, pero adems tendrn un ttulo, y se podrn desplazar (se simula el desplazamiento de una ventana).

La clase derivada heredar los atributos de la clase base y los mtodos, adems tendr un atributo ms, el ttulo de la ventana. package windows public class VentanaTitulo extends Ventana{ // Atributos protected String titulo; // Constructor public VentanaTitulo(int posX, int posY, int ancho, int alto, String nombre) { super(posX, posY, ancho, alto); titulo = nombre; }

// Mtodos public void mostrar(){ System.out.println("Titulo: " + titulo); super.mostrar(); }


public void desplazar(int posX, int posY){ super.posX += posX; super.posY += posY; } } La primera instruccin del constructor de la clase derivada es una llamada al constructor de la clase base mediante la palabra reservada super. La llamada: super(posX, posY, ancho, alto);

Inicializa los cuatro atributos de la clase base Ventana: posX, posY, ancho, alto. A continuacin, se inicializan los atributos de la clase derivada, y se realizan las tareas de inicializacin que sean necesarias. Si no se llama explcitamente al constructor de la clase base. Java lo realiza por nosotros, llamando al constructor por defecto si existe.
El mtodo denominado desplazar() cambia la posicin de la ventana, aadindoles el desplazamiento. En la clase derivada se define un mtodo que tiene el mismo nombre y los mismos parmetros que la de la clase base. Se dice que redefinimos el mtodo mostrar() en la clase derivada. El mtodo mostrar() de la clase derivada VentanaTitulo hace una llamada al mtodo mostrar() de la clase base Ventana, mediante la instruccin: super.mostrar();

De este modo aprovechamos el cdigo ya escrito, y le aadimos el cdigo que describe la nueva funcionalidad de la ventana por ejemplo, que muestre el ttulo. Si nos olvidamos de poner la palabra reservada super llamando al mtodo mostrar(), tendramos un mtodo recursivo. El mtodo mostrar() llamara a mostrar() indefinidamente.
package windows; public class VentanaApp { public static void main(String[] args) { VentanaTitulo ventana = new VentanaTitulo(0, 0, 20, 30, "Principal"); System.out.println("Datos de la ventana despus de crearla:"); ventana.mostrar(); ventana.cambiarDimensiones(10, 15); ventana.desplazar(4, 3); System.out.println("Datos de la ventana despus de cambiar dimensin y desplazarla); ventana.mostrar(); } }

S-ar putea să vă placă și