Sei sulla pagina 1di 121

Herencia

En
JAVA
V8.0
Marzo 2015
Ferreiras

Ferreiras Herencia en JAVA 1


Parte I

Ferreiras Herencia en JAVA 2


Herencia
Es la capacidad de una clase para usar los
atributos y mtodos de otra clase mientras
agrega su propia funcionalidad. Define un tipo
derivado de otro ya existente, llamado base,
compartiendo los atributos y mtodos sin
tener que volver a implementarlos de nuevo.

Ferreiras Herencia en JAVA 3


La sintaxis para la herencia en java es:

class Derivada extends Base {


//..
}

Es la palabra clave
de java para
indicar herencia

Ferreiras Herencia en JAVA 4


Por ejemplo:

/*

Herencia0.java
jdk1.6.0_25

Ferreiras / JAVA / Herencia

*/

import java.text.DecimalFormat;

Ferreiras Herencia en JAVA 5


class Libro {

private int paginas;

Libro() {
paginas = 555;
}

public void setPaginas( int numPaginas ) {


paginas = numPaginas;
}

public int getPaginas() {


return paginas;
}
}

Ferreiras Herencia en JAVA 6


class Diccionario extends Libro {

private int definiciones;

Diccionario() {
definiciones = 33333;
}

double relacion() {
return (double) definiciones / getPaginas();
}

void setDefiniciones( int numDefiniciones ) {


definiciones = numDefiniciones;
}

int getDefiniciones() {
return definiciones;
}
}

Ferreiras Herencia en JAVA 7


public class Herencia0{

public static void main(String[ ] args){

DecimalFormat formato1 = new DecimalFormat("0.###");


DecimalFormat formato2 = new DecimalFormat("###,###");
Diccionario d1 = new Diccionario();
System.out.println("\n\t=> Numero de paginas por default: " +
formato2.format( d1.getPaginas()) +
"\n\t=> Numero definiciones por default: " +
formato2.format( d1.getDefiniciones() ) );
d1.setPaginas(943);
d1.setDefiniciones(45000);
System.out.println("\n\t=> Numero de paginas: " + d1.getPaginas() +
"\n\t=> Numero de definiciones: " +
formato2.format( d1.getDefiniciones() ) +
"\n\t=> Relacion definiones a paginas: " +
formato1.format( d1.relacion() ) + "\n\n");
System.out.printf("\n\t=> Definiciones: %,d", d1.getDefiniciones() );
}
Es otra forma de formatear
} nmeros. Es estilo C. No es
recomendada.
Ferreiras Herencia en JAVA 8
/*

C:\Program Files\Java\jdk1.6.0_22\bin>java Herencia0

=> Numero de paginas por default: 555


=> Numero definiciones por default: 33,333

=> Numero de paginas: 943


=> Numero de definiciones: 45,000
=> Relacion definiones a paginas: 47.72

=> Definiciones: 45,000

C:\Program Files\Java\jdk1.6.0_22\bin>

*/

Ferreiras Herencia en JAVA 9


En el ejemplo anterior Herencia0.java
vemos que:
La clase Diccionario extends a la clase Libro,
esto es, la hereda.

La clase derivada Diccionario, de la clase base


Libro, hereda los mtodos y los atributos de dicha
clase base, con sus respectivos derechos de
acceso;
La clase Diccionario agrega sus propias
funcionalidades y un nuevo atributo;

Ferreiras Herencia en JAVA 10


El objeto diccionario se crea con la cantidad de
paginas por defecto en la clase Libro y con la
cantidad de definiciones por defecto en su clase.
Aqu hay un asunto de constructores que veremos
mas adelante;

El objeto Diccionario usa los mtodos


setPaginas() y getPaginas() de la interfaz de la
clase Libro;

Ferreiras Herencia en JAVA 11


El objeto Diccionario usa los mtodos relacion(),
setDefiniciones() y getDefiniciones() de la interfaz
de su clase;

Si un mtodo de la clase base es private,


entonces el objeto de la clase derivada no lo podr
acceder; Solo podra hacerlo va la interfaz de la
clase base.

Ferreiras Herencia en JAVA 12


Otros nombres usados son superclase
(superclass) o padre (parent class) como
sinnimo de clase base; Y, subclase
(subclass) o hija (child class) o
descendiente (descendant) como sinnimo
de clase derivada.

Ferreiras Herencia en JAVA 13


Visibilidad o alcance
Si en el ejemplo Herencia0b.java
intentamos implementar en la clase
derivada Diccionario el mtodo:
void mostrar() {
System.out.println("\n\t=> Autor: " + autor );
System.out.println("\n\t=> Autor: " + getAutor() );
System.out.println("\n\t=> paginas: " + paginas );
}

No hay acceso a estos


miembros. No son heredados.
Son private.
Ferreiras Herencia en JAVA 14
Tendramos los siguientes errores:
C:\Program Files\Java\jdk1.6.0_22\bin>javac Herencia0b.java

Herencia0b.java:56: autor has private access in Libro


System.out.println("\n\t=> Autor: " + autor );
^
Herencia0b.java:57: cannot find symbol
symbol : method getAutor()
location: class Diccionario
System.out.println("\n\t=> Autor: " + getAutor() );
^
Herencia0b.java:58: paginas has private access in Libro
System.out.println("\n\t=> paginas: " + paginas );
^

Ferreiras Herencia en JAVA 15


La causa de dichos errores es porque
la variable autor y el mtodo getAutor()
son private en la clase, esto es, estn
encapsulados y no tienen visibilidad o
alcance fuera de dicha clase. Solo
incluyendo mtodos en su interfaz para
accederlos es que podramos usarlos.
Los miembros private no son
heredados !!.
Ver el ejemplo Herencia0b.java completo en el grupo.

Ferreiras Herencia en JAVA 16


protected, #
protected Significa que el miembro es accesible
directamente dentro de la clase base y su derivada.
En JAVA, tambin son accedidos por todas las
otras clases en el mismo package ( A ver mas
adelante).
protected Tambin significa que el miembro es
accesible directamente (sin necesidad de usar la
interfaz de la clase base) por un objeto de la clase
derivada. ( Ver mas adelante Herencia0g.java. )

Ferreiras Herencia en JAVA 17


Revisitando los niveles de acceso a los miembros de la clase, ahora
considerando la herencia:

C1 C2 C3 C4 C5

Modificador de Misma Fuera de la Mismo otros


Subclase
acceso clase clase package packages

public SI SI SI SI SI
protected SI NO SI SI NO
no access modifier SI NO NO SI NO
private SI NO NO NO NO

En la tabla anterior :
C1 indica si la clase misma tiene acceso al miembro definido por el nivel de acceso.
Como se puede ver, una clase siempre tiene acceso a sus propios miembros.
C2 Indica que el acceso fuera de la clase.
C4 indica si las clases en el mismo paquete que de la clase (sin importar su parentesco)
tienen acceso al miembro.
C3 indica si las subclases de la clase declarada fuera de este paquete tienen acceso al
miembro.
C5 indica si todas las clases tienen acceso al miembro.

Ferreiras IMPLEMENTACION Y USO DE 18


CLASES EN JAVA
/*
Herencia0g.java

Ferreiras / Java / Herencia / Constructores

Los objetos de la clase Derivada tienen


acceso directo ( sin necesidad de usar la interfaz
de la clase base) a los miembros protected y
public en la clase Base

*/

Ferreiras Herencia en JAVA 19


class A {

private int x;
protected double y;

public A() { }

public A( int x, double y ) {


this.x = x;
this.y = y;
}

protected int getX() { return x; }

public double getY() { return y; }

Ferreiras Herencia en JAVA 20


class B extends A {

private String nombre;

public B( int x, double y, String no ) {


super(x,y);
nombre = no;
}

Ferreiras Herencia en JAVA 21


public class Herencia0g {
public static void main( String [ ] fofi ) {
B b1 = new B( 123, 45.67, "El Lento");
System.out.println("\n" + b1.getX() );

b1.y = 6.7984;
System.out.println("\n" + b1.getY() );

}
}

Ferreiras Herencia en JAVA 22


/*

D:\Ferreiras2\Java, Mi Codigo>javac Herencia0g.java

D:\Ferreiras2\Java, Mi Codigo>java Herencia0g

123

6.7984

D:\Ferreiras2\Java, Mi Codigo>

*/

Ferreiras Herencia en JAVA 23


Otro ejemplo, Si declaramos protected la
variable paginas y el mtodo getAutor() en la
clase Libro, ya no se generaran los errores
de visibilidad indicados antes y el cdigo
compilara y se ejecutara sin problemas:
class Libro { protected le
protected int paginas;
protected String autor;
garantiza a la
protected String getAutor() { clase derivada
return autor; poder acceder a
}
//... Ver Herencia0c.java
dichos miembros
} en la base.

Ferreiras Herencia en JAVA 24


Otro Ejemplo: /*
Herencia1.java
jdk1.6.0_25

Ferreiras / JAVA / Herencia

*/

class Libro{
protected int paginas;

Libro(){
paginas = 555;
}

public void setPaginas( int numPaginas ){


paginas = numPaginas;
}

public int getPaginas(){


return paginas;
}

}
Ferreiras Herencia en JAVA 25
class Diccionario extends Libro{

private int definiciones;


Acceso directo a un atributo
Diccionario(){ protected heredado de la
definiciones = 33333; clase base Libro
}

double relacion(){
return (double) definiciones / paginas;
}

void setDefiniciones( int numDefiniciones ){


definiciones = numDefiniciones;
}

int getDefiniciones(){
return definiciones;
}
}

Ferreiras Herencia en JAVA 26


Acceso indirecto (con un objeto
public class Herencia1{ de la clase derivada ) a un
mtodo de la clase base
public static void main(String[ ] args){

Diccionario d1 = new Diccionario();


System.out.println("\n\t=> Numero de paginas: " + d1.getPaginas() +
"\n\t=> Numero de definiciones: " + d1.getDefiniciones() +
"\n\t=> Relacion definiones a paginas: " + d1.relacion() +
"\n\n");
}

Ferreiras Herencia en JAVA 27


/*

C:\Archivos de programa\Java\jdk1.6.0_25\bin> java Herencia1

=> Numero de paginas: 555


=> Numero de definiciones: 33333
=> Relacion definiones a paginas: 60.05945945945946

C:\Archivos de programa\Java\jdk1.6.0_25\bin>

*/

Ferreiras Herencia en JAVA 28


OJO: En JAVA, el acceso
protected es muy amplio, por lo
tanto, es mejor tener todas las
variables miembro private; Si se
requiere acceder a estas ultimas en
la clase derivada es mejor declarar
los mtodos de acceso protected, en
la base. As, solo las derivadas
podrn acceder.

Ferreiras Herencia en JAVA 29


En el ejemplo Herencia0d.java las
variables son private y los mtodo getAutor()
y getPaginas() son protected. Luego:
class Libro{
Las variables son
private int paginas; private y los mtodos
private String autor;
protected. Luego, la
protected String getAutor(){ derivada las accede sin
return autor; problema en su mtodo
}
mostrar.
protected int getPaginas(){
return paginas;
}
// Ver Herencia0d.java

}
Ferreiras Herencia en JAVA 30
La clase Object en JAVA
Es la superclase de todas las clases de
JAVA, de manera directa o indirecta todas
las clases derivan de ella. Es la clase raz. Si
extends no aparece al definir una nueva
clase, JAVA considera que dicha clase
desciende directamente de la superclase
Object.

Ferreiras Herencia en JAVA 31


La clase Object aporta a sus
descendientes mtodos tales como clone(),
equals(), copy(Object src), finalize(),
getClass(), notify(), toString(), wait(), entre
otros. Ver en
http://docs.oracle.com/javase/7/docs/api/index.html

Informacin completa de la clase Object.

Ferreiras Herencia en JAVA 32


Mtodos en la clase Objetc
protected Object clone() ; Creates and returns a copy of this object.
boolean equals(Object obj); Indicates whether some other object is "equal to" this one.
protected void finalize(); Called by the garbage collector on an object when garbage collection determines
that there are no more references to the object.
Class<?> getClass(); Returns the runtime class of this Object.
int hashCode(); Returns a hash code value for the object.
void notify(); Wakes up a single thread that is waiting on this object's monitor.
void notifyAll(); Wakes up all threads that are waiting on this object's monitor.
String toString(); Returns a string representation of the object.
void wait(); Causes the current thread to wait until another thread invokes the notify() method or the
notifyAll() method for this object.
void wait(long timeout); Causes the current thread to wait until either another thread invokes the notify()
method or the notifyAll() method for this object, or a specified amount of time has elapsed.
void wait(long timeout, int nanos); Causes the current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread,
or a certain amount of real time has elapsed.

Ferreiras Herencia en JAVA 33


Herencia mltiple ? NO. En java solo
podemos extends una sola clase. No existe
la herencia mltiple. Aunque si podemos
usar interface ( a ver mas adelante ) para
truquear e implementar una especie de
herencia mltiple, pero nunca como en
C++;

Ferreiras Herencia en JAVA 34


Constructores en la Herencia
En los ejemplos anteriores Se usaron los
constructores por defecto suplidos por la JVM.

En la construccin de los objetos


involucrados en una jerarqua de herencia
primero se construye el objeto de la clase base
y luego el objeto de la clase derivada; Ver mas
adelante Herencia0f.java

Ferreiras Herencia en JAVA 35


Por ejemplo:

/*
Herencia0f.java
jdk1.6.0_22

Ferreiras / JAVA / Herencia / Constructores en la herencia

A vehicle (from Latin: vehiculum[1]) is a device that is designed or used to


transport people or cargo. Most often vehicles are manufactured, such as
bicycles, cars, motorcycles, trains, ships, boats, and aircraft.

Vehicles that do not travel on land often are called craft, such as watercraft,
sailcraft, aircraft, hovercraft, and spacecraft.

*/

Ferreiras Herencia en JAVA 36


class Vehiculo {
Vehiculo() {
System.out.println("\n\t=> Un Vehiculo creado\n" );
}
}

class VehiculoTerrestre extends Vehiculo {


VehiculoTerrestre() {
System.out.println("\n\t=> Un vehiculo terrestre creado\n" );
}
}

class Bicicleta extends VehiculoTerrestre {


Bicicleta() {
System.out.println("\n\t=> Una Bicicleta creada\n" );
}
}

Ferreiras Herencia en JAVA 37


public class Herencia0f {

public static void main(String [ ] args){

Bicicleta t = new Bicicleta();


}
}

C:\Program Files\Java\jdk1.6.0_22\bin> java Herencia0f

=> Un Vehiculo creado Obsrvese el orden en que


son creados primeramente
=> Un vehiculo terrestre creado los objetos de las clases
base respectivamente.
=> Una Bicicleta creada

C:\Program Files\Java\jdk1.6.0_22\bin>

Ferreiras Herencia en JAVA 38


Constructores en la Herencia
En el constructor de la clase derivada se
debe suplir la informacin necesaria para
construir primero el objeto base y luego el
derivado;

Dos palabras reservadas son usadas en


Java para los constructores en la herencia:
this
super

Ferreiras Herencia en JAVA 39


this, super
"this" Es una referencia al objeto actual;
Permite a un objeto referirse a si mismo.
Dentro de un mtodo no static, this puede ser
usado para hacer referencia al objeto que se
est ejecutando, el objeto a travs del cual se
invoca el mtodo.

"super" Es una referencia a la clase base;

Ferreiras Herencia en JAVA 40


this, super
Recordemos que dentro de una definicin de clase, puede utilizar
la palabra clave this para referirse a la instancia actual de la clase.

Del mismo modo, la palabra clave super se refiere a la superclase,


que podra ser el padre inmediato o su ancestro.

La palabra clave super permite la subclase para acceder a


'mtodos y variables dentro de la subclase' superclase definicin.

Por ejemplo, super() y super(argumentList) se pueden utilizar para


invocar el constructor de la superclase '. Si la subclase sobreescribe
un mtodo heredado de su superclase, digamos getArea(), puede
utilizar super.getArea() para invocar la versin de superclase dentro
de la definicin de subclase.

Ferreiras Herencia en JAVA 41


this, super
Del mismo modo, si la subclase oculta una variable
de la superclase ', puede utilizar super.variableName
para hacer referencia a la variable oculta, dentro de la
definicin de subclase: SOLO SI ESTA NO TIENE
ACCESO private en la superclase;
( Ver Lab05101302.java )

Ferreiras Herencia en JAVA 42


Por ejemplo, en el cdigo Herencia0e.java :
Mtodo de la clase
derivada Invoca el Mtodo
de la clase base

void prender() {
if( bateria ) Invoca el Mtodo de la
super.prender(); clase derivada
else{
this.recargarBateria();
super.prender();
}

Invoca el Mtodo
de la clase base

Ver el ejemplo Herencia0e.java completo en el grupo.


Ferreiras Herencia en JAVA 43
El uso de this en mtodos y
constructores
En un mtodo no static, this se refiere a
la instancia de la clase que esta ejecutando
el mtodo;

En un constructor, this se refiere a otro


constructor de la misma clase con una lista
de parmetros diferentes;

Ferreiras Herencia en JAVA 44


Por ejemplo, this en un mtodo:

Aqu se refiere a la
void prender() { instancia de la clase
if( bateria ) que ejecute el mtodo
super.prender(); recargarBateria()
else{
this.recargarBateria();
super.prender();
}
}

Ver el ejemplo Herencia0e.java completo en el grupo.

Ferreiras Herencia en JAVA 45


Por ejemplo, this en un constructor:
class Vehiculo {

private String marca;


private double precio;

Vehiculo ( String ma, double pr ) { Aqu, This esta usando


marca = ma;
este constructor
precio = pr;
}

Vehiculo() {
this( "Por default es Carabelita", 5678.23 ); // default explicito
}

void verVehiculo() {
System.out.println("\n\t=> El vehiculo actual es " + marca +
" y cuesta " + precio + "\n" );
}

Ver el ejemplo Herencia0i.java completo en el grupo.


Ferreiras Herencia en JAVA 46
El uso de super en mtodos
y constructores
En un mtodo no static, super se refiere
a la clase base;

En un constructor de una derivada,


super se refiere a un constructor de la
clase base;

Ferreiras Herencia en JAVA 47


Por ejemplo, super en un mtodo:

void prender() { En ambos casos, super se


if( bateria ) refiere a la clase base que
super.prender(); tiene el mtodo prender()
else{
this.recargarBateria();
super.prender();
}
}

Ver el ejemplo Herencia0e.java completo en el grupo.

Ferreiras Herencia en JAVA 48


Por ejemplo, super en un constructor de
una clase derivada:
class Gerente extends Empleado {
class Empleado {
private String nombre; private int departamento;
private double salario;
Gerente( String no, double sa, int de) {
Empleado() {
nombre = "Grandote Perez"; super(no, sa);
salario = 8367.00; departamento = de;
} }

Empleado( String n, double s) { }


nombre = n;
salario = s; Aqu, super se refiere al
} constructor de la clase
base
}

Ferreiras Herencia en JAVA 49


Mas del uso de this y super en la herencia

// 1) // Lo correcto sera:

=> Si intentamos class Base{

class Base{ Base() { } // default explcito.


Base( double s) { }
Base( double s) {
// ... }
}} class Derivada extends Base { } // OK

class Derivada extends Base { }


La Derivada requiere que la base
ERROR
tenga un constructor por defecto
explicito. Esto as porque:
Herencia0g.java:16: cannot find symbol a) En este cdigo no se establece
symbol : constructor Base() explcitamente el constructor de la
location: class Base base a usar y, como la base ya tiene
class Derivada extends Base { } // ERROR uno definido, que no es por defecto,
la Derivada espera encontrarlo.

Ferreiras Herencia en JAVA 50


Mas del uso de this y super en la herencia

// 2) => Si intentamos

class Empleado { ERROR


private String nombre;
private double salario; Herencia0g.java:56: cannot find symbol
symbol : constructor Empleado()
Empleado( String n, double s){ location: class Empleado
nombre = n; super();
salario = s; ^
}
}

class Gerente extends Empleado {

private int departamento;


Para usar super(), como
Gerente( String no, double sa, int de) { planteado, se deber haber
definido en la base un
super();
departamento = de; constructor Empleado() { //... }
}
}

Ferreiras Herencia en JAVA 51


Mas del uso de this y super en la herencia

// Lo correcto seria:

class Empleado {
private String nombre;
private double salario;

Empleado() {
nombre = "Grandote Perez";
salario = 8367.00;
}

Empleado( String n, double s){


nombre = n;
salario = s;
}
}

class Gerente extends Empleado {


private int departamento;
Gerente( String no, double sa, int de) {
super();
departamento = de;
}
}

Ferreiras Herencia en JAVA 52


Mas del uso de this y super en la herencia

class Gerente extends Empleado {


// 3)
private int departamento;
// => Si intentamos
Gerente( String no, double sa, int de) {
class Empleado {
private String nombre; super();
private double salario; super(no, sa); Dos
departamento = de; constructores
Empleado() { } para el mismo
nombre = "Grandote Perez"; objeto !!
salario = 8367.00; }
}
// ERROR
Empleado( String n, double s){
nombre = n; Herencia0g.java:139: call to super must be first
salario = s; statement in constructor
} super(no, sa);
} ^

Ferreiras Herencia en JAVA 53


Mas del uso de this y super en la herencia

class Gerente extends Empleado {

// Lo correcto seria private int departamento;

class Empleado { Gerente( String no, double sa, int de) {


private String nombre;
private double salario; // super();
super(no, sa);
Empleado() { departamento = de;
nombre = "Grandote Perez"; }
salario = 8367.00;
} }

Empleado( String n, double s){


nombre = n;
salario = s;
} Hay que usar un
constructor, uno solo, y
}
tiene que estar definido en
la clase base. !!!

Ferreiras Herencia en JAVA 54


Mas de constructores en la Herencia
Ya que cada objeto "contiene" una instancia
de la clase base, ste debe ser inicializado;

El compilador de JAVA inserta,


automticamente, una llamada al constructor
por defecto de la clase base;

La llamada se inserta como la primera


sentencia de cada constructor de la derivada;

Ferreiras Herencia en JAVA 55


La ejecucin de los constructores procede
de arriba hacia abajo en la jerarqua de
herencia;

De esta manera, cuando un mtodo de la


clase descendiente se ejecuta (constructor
incluido), la superclase est completamente
inicializada;

Ferreiras Herencia en JAVA 56


El constructor por defecto suplido por el
compilador "desaparece" si el desarrollador
define sus propios constructores;

De manera explicita, el constructor de la clase


derivada debe llamar al constructor de la clase
base;

Ferreiras Herencia en JAVA 57


Use super() para identificar a los
constructores de la clase base; Debe ser la
primera sentencia en el constructor de la
clase derivada;

Si se definen constructores con


argumentos y el constructor por defecto no
se define explcitamente, el compilador no
puede insertar la llamada
automticamente.

Ferreiras Herencia en JAVA 58


Parte II

Ferreiras Herencia en JAVA 59


Clases y mtodos abstract
Clase abstracta
Es declarada con la palabra reservada abstract:

<modificador> abstract class Animal {


// ...
}

Segn las especificaciones de Java, puede o no incluir uno o


ms mtodos abstract. ( FF: Si no tiene mtodos abstractos, no
tendra sentido la clase abstracta ).
No permite ser instanciada. Slo se puede usar como clase Base
de una clase Derivada, que la ampla;
La clase Derivada de una clase Base que es abstract debe
implementar todos los mtodos abstract, sino lo hace debe ser
declarada tambien abstract;
Ferreiras Herencia en JAVA 60
Clases y mtodos abstract
Mtodos abstractos
No tienen cuerpo, solo la firma.
Su declaracin termina con un punto y coma (;).
La sintaxis general para declarar la firma del mtodo abstracto es

<modificador> abstract tipoRetorno nombreMetodo( );

Si una clase incluye mtodos abstractos, la clase misma se debe declarar


abstracta.
FF: Si la clase es abstracta, no tendra sentido que no tuviese uno o ms
mtodos abstractos. Ver ms adelante Para que clases abstractas?

Ferreiras Herencia en JAVA 61


Clases y mtodos abstract
Para que clases abstractas?
La razn de ser de una clase abstracta es para
resolver situaciones en las cuales se requiere definir
una clase Base que declare la estructura de una
abstraccin sin proveer la implementacin completa
del mtodo. Esto es, se quiere tener una clase que
solamente defina una forma generalizada que ser
compartida por todas sus derivadas, permitiendo a
cada una de stas completar los detalles en la
implementacin de dichos mtodos abstractos.

Ferreiras Herencia en JAVA 62


/*
Por ejemplo: Herencia0h.java
jdk1.6.0_25

Ferreiras / Java / Herencia / Clases abstract

*/
Clase abstract
abstract class Animal {

private String nombre;

public Animal( String no ) {


nombre = no;
}

public String getNombre() {

return nombre;
Mtodo abstract
}

public abstract void hablar();

}
Ferreiras Herencia en JAVA 63
class Perro extends Animal {

Perro ( String nom ){


super("Canino"); Implementacin del mtodo
} abstract declarado en la clase
base abstrac
public void hablar() {

System.out.println("\n\t=> Hago jau jau jau \n");


}

Ferreiras Herencia en JAVA 64


/*

public class Herencia0h {

public static void main( String [ ] args ) {

Animal unAnimal = new Animal( "Lukas"); Obsrvese que al


} instanciar la clase
} abstracta se gener un
error
ERROR

C:\Archivos de programa\Java\jdk1.6.0_25\bin>javac Herencia0h.java


Herencia0h.java:48: Animal is abstract; cannot be instantiated
Animal unAnimal = new Animal( "Lukas");
^

*/

Ferreiras Herencia en JAVA 65


public class Herencia0h {

public static void main( String [ ] args ) {

Perro unPerro = new Perro( "Lukas");


System.out.println( "\n\t=> Hola, soy " + unPerro.getNombre() + " y, " );
unPerro.hablar();
}
}

Ferreiras Herencia en JAVA 66


C:\Archivos de programa\Java\jdk1.6.0_25\bin> java Herencia0h

=> Hola, soy Canino y,

=> Hago jau jau jau

C:\Archivos de programa\Java\jdk1.6.0_25\bin>

Ferreiras Herencia en JAVA 67


No necesariamente Una clase que sea
declarada abstract debe tener mtodos
abstract.

...

Ferreiras Herencia en JAVA 68


La clase que contiene mtodos
abstract No puede ser usada para crear
objetos.

Si la clase derivada hereda o declara


un mtodo abstract y no lo
implementa debe, entonces, ser declara
como clase abstract.

Ferreiras Herencia en JAVA 69


Clase concreta Es una clase con la cual
se pueden crear objetos, esto es, puede ser
instanciada para crear variables de
instancia. Es lo opuesto a la clase abstract:
Declara lo que las
derivadas (concretas)
tienen en comn.

La clase abstract java.lang.Number y algunas de sus


derivadas o clases concretas.

Ferreiras Herencia en JAVA 70


final en Herencia
final es una palabra reservada que es usada
en la declaracin de una clase para evitar que
otros desarrolladores puedan crear clases
derivadas de sta. Es lo opuesto a la palabra
reservada abstract:

<modificador> final class NombreClase {


...
}

See on page 465, idem and page 438 on Big java

Ferreiras Herencia en JAVA 71


Por ejemplo, La clase String de la
librera estndar de java ha sido declara
como: public final class String {
//...
}

Eso significa que nadie puede hacer


extends a la clase String.

Ferreiras Herencia en JAVA 72


Tambin los mtodos pueden ser
declarados final Para evitar que otros
programadores los puedan sobreescribir
(overriding):

<modifificador> class Derivada extends Base {


<modificador> final tipoRetorno nombreMetodo( ) {
...
}
}

See on page 465, idem and page 438 on Big java

Ferreiras Herencia en JAVA 73


Overloading o sobrecarga de
mtodos en JAVA
Significa definir dos o ms mtodos dentro
de la misma clase, los cuales tienen el
mismo nombre, pero con diferentes
declaraciones de parmetros. Los tipos de
retornos podrn ser iguales o diferentes. Lo
nico que se toma en cuenta son los
nombres de los mtodos y sus listas de
parmetros.

Ferreiras Herencia en JAVA 74


Cuando un mtodo sobrecargado se
invoca, Java utiliza el tipo y / o nmero de
argumentos como gua para determinar qu
versin del mtodo sobrecargado debe
llamar.

Cuando Java encuentra una llamada a


un mtodo sobrecargado, simplemente
ejecuta la versin del mtodo cuyos
parmetros coincidan con los argumentos
utilizados en la llamada
Ferreiras Herencia en JAVA 75
Por ejemplo:

overload0.java
jdk1.6.0_25

Ferreiras / JAVA / Sobrecarga de mtodos (Overloading )

class Sobrecargada {
void fofi(String cad1) {
System.out.println( "\n\t=> " + cad1 );
}

void fofi(String cad, String cad2) {


System.out.println( "\n\t=> Concatenando: " + cad + " " + cad2 );
}

double fofi(double salarioAnual) {


System.out.println("\n\t=> Salario anual: " + salarioAnual );
return salarioAnual/12;
}
}

Ferreiras Herencia en JAVA 76


public class Overload0 {

public static void main(String args[ ]) {

Sobrecargada sobrecarga = new Sobrecargada();


double salarioMensual;
sobrecarga.fofi("El monigote de la ONU");
sobrecarga.fofi( "Ban-Kimoon" , " y de la OTAN" );
salarioMensual = sobrecarga.fofi(435237.12);
System.out.println( "\n\t=> Salario Mensual = " + salarioMensual );
}
}

Ferreiras Herencia en JAVA 77


/*

C:\Archivos de programa\Java\jdk1.6.0_25\bin>java Overload0

=> El monigote de la ONU

=> Concatenando: Ban-Kimoon y de la OTAN

=> Salario anual: 435237.12

=> Salario Mensual = 36269.76

C:\Archivos de programa\Java\jdk1.6.0_25\bin>

*/

Ferreiras Herencia en JAVA 78


Cuando JAVA invoca un mtodo
sobrecargado busca una coincidencia entre
los argumentos usados para llamar el
mtodo y los parmetros del mtodo. No
obstante, esta coincidencia no tiene
necesita ser 100 % exacta. Veamos en el
siguiente ejemplo Overload0b.java:

Ferreiras Herencia en JAVA 79


Obsrvese que se
public class Overload0b { esta invocando fofi
con un int; PERO, no
public static void main(String args[ ]) { se ha definido el
mtodo fofi(int)
Sobrecargada sobrecarga = new Sobrecargada();
double salarioMensual;
sobrecarga.fofi("El monigote de la ONU");
sobrecarga.fofi( "Ban-Kimoon" , " y de la OTAN" );
salarioMensual = sobrecarga.fofi(435237.12);
int entero = 1234;
salarioMensual = sobrecarga. fofi(entero) ; // Invocara fofi( double ); <==
System.out.println( "\n\t=> Salario Mensual = " + salarioMensual );
}
}
Luego, JAVA har la conversin a double
automticamente por el mecanismo de promocin int
a double, y llamar a fofi(double)

Ferreiras Herencia en JAVA 80


C:\Program Files\Java\jdk1.6.0_22\bin>java Overload0b

=> El monigote de la ONU

=> Concatenando: Ban-Kimoon y de la OTAN

=> Salario anual: 435237.12

=> Salario anual: 1234.0 <== NOTESE LA CONVERSION A double

=> Salario Mensual = 102.83333333333333

C:\Program Files\Java\jdk1.6.0_22\bin>

Ver el ejemplo Overload0b.java completo en el grupo.

Ferreiras Herencia en JAVA 81


En el ejemplo anterior (Overload0b.java)
podemos ver que el cdigo no defini un
mtodo fofi(int) sino un mtodo fofi(double).
En esta situacin JAVA realizar la conversin
automtica del tipo int a double y luego
llamar el mtodo fofi(double).

Ferreiras Herencia en JAVA 82


En resumen, los mtodos sobrecargados:
Tienen diferentes listas de parmetros;
Los tipos de retorno pueden ser iguales o
diferentes. No importa;
Pueden cambiar el modificador de acceso;
Pueden declarar nuevas o ms amplias
excepciones;
Pueden estar en la misma clase o en una
clase derivada;

Ferreiras Herencia en JAVA 83


Overriding
[ sobreescritura de mtodos ]
Es una nueva definicin, en una clase
derivada, de un mtodo no static ya
definido en la clase base. El mtodo
sobrescrito tendr en la clase derivada el
mismo modificador, el mismo tipo de retorno,
el mismo nombre y la misma lista de
parmetros, pero cuerpo diferente.

Ferreiras Herencia en JAVA 84


En situaciones en las que sea necesario
usar de manera explcita el mtodo de la
clase base podemos usar la palabra
reservada super y para llamar de manera
expresa un mtodo del objeto actual
podemos usar la palabra reservada this.

La nueva definicin del mtodo no


puede reducir la accesibilidad del mtodo
original, pero si puede ampliarla.
Ferreiras Herencia en JAVA 85
Herencia2.java
jdk1.6.0_25

Ferreiras / JAVA / Herencia / Overriding

class Animal {

public void mover() {


System.out.println("\n\t=> Un animal se mueve !!\n");
}
}

class Perro extends Animal {

public void mover() { // Override el metodo mover()


System.out.println("\n\t=> AVISO: Los perros pueden caminar, correr y morder\n");
}

Ferreiras Herencia en JAVA 86


public class Herencia2{

public static void main(String args[]){

Animal unAnimal = new Animal(); // referencia un objeto Animal


unAnimal.mover(); // Ejecuta el metodo mover en la clase base

Animal otroAnimal = new Perro(); // referencia un objeto Perro


otroAnimal.mover(); // Ejecuta el metodo mover() en la clase Perro

}
}

Ferreiras Herencia en JAVA 87


/*

C:\Archivos de programa\Java\jdk1.6.0_25\bin>java Herencia2

=> Un animal se mueve !!

=> AVISO: Los perros pueden caminar, correr y morder

C:\Archivos de programa\Java\jdk1.6.0_25\bin>

*/

Ferreiras Herencia en JAVA 88


/*
Herencia2a.java
jdk1.6.0_25

Ferreiras / JAVA / Herencia / Overriding / super

*/

class Animal {

public void mover() {


System.out.println("\n\t=> Un animal se mueve !!\n");
}
}

Ferreiras Herencia en JAVA 89


class Perro extends Animal {

public void mover() {


super.mover(); // invoca el metodo mover de la clase base
System.out.println("\n\t=> AVISO: Los perros pueden caminar, correr y morder\n");
}

public class Herencia2a {

public static void main(String args[]){

Animal unAnimal = new Perro(); // referencia un objeto Perro


unAnimal.mover(); // Ejecuta el metodo en la clase Perro

}
}

Ferreiras Herencia en JAVA 90


/*

C:\Archivos de programa\Java\jdk1.6.0_25\bin> java Herencia2a

=> Un animal se mueve !!

=> AVISO: Los perros pueden caminar, correr y morder

C:\Archivos de programa\Java\jdk1.6.0_25\bin>

*/

Ferreiras Herencia en JAVA 91


/*
Herencia2b.java
jdk1.6.0_25

Ferreiras / JAVA / Herencia / Overriding /

*/

class Animal {

public void mover() {


System.out.println("\n\t=> Un animal se mueve !!\n");
}
}

Ferreiras Herencia en JAVA 92


class Perro extends Animal {

public void mover() {


super.mover(); // invoca el metodo mover de la clase base
System.out.println("\n\t=> AVISO: Los perros pueden caminar, correr y morder\n");
}

public void ladrar() {


System.out.println("\n\t=> URGENTE !! Estoy ladrando\n");
}

Ferreiras Herencia en JAVA 93


public class Herencia2b {

public static void main(String args[]){

Animal unAnimal = new Perro();


unAnimal.mover(); // Ejecuta el metodo en la clase Perro
unAnimal.ladrar(); //

} Generar un error en
} tiempo de compilacin
porque se esta
invocando un mtodo
de la clase Derivada
con una referencia de la
clase Base.

Ferreiras Herencia en JAVA 94


/*

C:\Archivos de programa\Java\jdk1.6.0_25\bin>javac Herencia2b.java


Herencia2b.java:58: cannot find symbol
symbol : method ladrar()
location: class Animal
Error generado en
unAnimal.ladrar(); //
tiempo de compilacin
^
porque se esta
1 error
invocando un mtodo
de la clase Derivada
C:\Archivos de programa\Java\jdk1.6.0_25\bin>
con una referencia de la
clase Base.
*/

Ferreiras Herencia en JAVA 95


En resumen, para sobreescribir los
mtodos en la clase base:
La lista de parmetros en el mtodo sobreescrito debe ser exactamente la
misma que la lista del mtodo en la clase base;

El tipo de retorno en el mtodo sobreescrito debe ser exactamente el


mismo tipo que el del mtodo en la clase base o un subtipo de este.

El nivel de acceso en el mtodo sobreescrito no puede ser mas restrictivo


que el del mtodo original en la clase base. Aunque si puede ser menor.

Los mtodos de instancia pueden ser sobreescritos solo si son heredados


por la clase derivada; Recordemos que los miembros private no son
heredados.

Ferreiras Herencia en JAVA 96


Los mtodos declarados final no pueden ser sobreescritos;

Un mtodo declarado static no puede ser sobreescrito pero puede ser


redeclarado;

Si un mtodo no puede ser heredado, este no puede ser sobreescrito;

Una clase derivada en el mismo package de la clase base puede


sobreescribir cualquier mtodo de clase base que no se declara private o
final;

Una clase derivada en un package diferente al de la clase base puede


sobreescribir cualquier metodo de la clase base solo si no es final y es public
o protected;

Un constructor no puede ser sobreescrito;

Ferreiras Herencia en JAVA 97


Jerarqua de Clases
[ Jerarqua de Herencia ]

Es un conjunto de clases en el cual hay


unas que son mas generales y otras que
son mas especializadas, siempre
manteniendo la relacin es-un | es-una
entre las clases base y las clases
derivadas.

Ferreiras Herencia en JAVA 98


Varias clases pueden ser declaras como
derivadas de una misma base. Las clases
derivadas, llamadas clases hermanas,
comparten los mismos atributos y
comportamientos en sus respectivas clases
bases.

Ferreiras Herencia en JAVA 99


La jerarqua de herencia forma una
estructura tipo rbol En la cual se
destacan:
La clase raz, Est en el tope de la jerarqua, de ella
descienden todas

Las ramas, Se compone de las clases debajo de la


raz que tienen mas derivadas;

Las hojas, Son clases derivadas que no tienen otras


derivadas. Son las clases terminales.

Ferreiras Herencia en JAVA 100


Por ejemplo:
Vehicle es la raz

FueledVehicle y
NonFueledVehicle son ramas

Car y Bicycle son hojas.

Bicycle desciende directamente


de NonFueledVehicle y tambin es
una derivada de Vehicle;

Ferreiras Herencia en JAVA 101


El mecanismo de herencia es
transitivo. Las caractersticas de las clases
pasan de una a otra. Es decir, una clase
base pasa sus caractersticas a su clase
derivada, sta la pasa a su derivada y as
sucesivamente. Las caractersticas
comunes deben estar situadas en el nivel
mas alto de la jerarqua.

Ferreiras Herencia en JAVA 102


De esta manera, las nicas
caractersticas expresamente establecidas
en las clases derivadas son las que las
hacen distintas a su clase base y a sus
hermanas ( derivan de la misma base ) en
la jerarqua.

Ferreiras Herencia en JAVA 103


Una caracterstica heredada podra
haberse originado en la clase base
inmediata o, posiblemente, varios niveles
ms altos en la jerarqua o antepasados
ms lejanos.

Ferreiras Herencia en JAVA 104


La jerarqua de herencia Maximiza el
potencial para la reutilizacin de las clases
y facilita las actividades de mantenimiento.
Esto ltimo es debido a que los cambios en
la base son reflejados automticamente en
sus derivadas.

Ferreiras Herencia en JAVA 105


Mas ejemplos

http://book.javanb.com/Programmers-Guide-to-Java-Certification-2nd/0201728281_ch06lev1sec1.html

Ferreiras Herencia en JAVA 106


Parte de la
jerarqua de las
clases de
componentes GUI.

Ferreiras Herencia en JAVA 107


Java Swing class hierarchy The class JComponent,
descended
. directly from Container, is the root class for
most of Swings user interface components

Recuperado de http://www.javabeginner.com/java-swing/java-swing-tutorial

Ferreiras Herencia en JAVA 108


*Conversin de objetos
[Casting Object]
(Opcional)
Casting un objeto es obtener una
referencia a ste, de diferente tipo, pero
coincidente, en una jerarqua de herencia.
El casting no cambia el objeto. Lo que
hace es que se crea una referencia
annima al objeto.

Ferreiras Herencia en JAVA 109


El casting de objetos lo que
Presenta es el uso de un objeto de un
tipo en lugar de otro tipo, entre los
objetos permitidos por la herencia y las
implementaciones. Es asignar un
objeto a otro, por medio de sus
respectivas variables de referencia.

Ferreiras Herencia en JAVA 110


Por ejemplo:
Cpu unCPU = new Cpu( "Ferrom9.99", 5.6);
IntelCPU unIntel = new IntelCPU("Core i7", 3.2, "low-power quad-core" );
AmdCPU unAMD = new AmdCPU("Opteron", 2.6, "AMD64 Technology");

Cpu servidorCPU; // variable referencia


servidorCPU = unAMD; // Conversion implicita
servidorCPU. enMarchaCPU(); En ambos casos,
unAMD.enMarchaCPU(); servidorCPU es una variable
de referencia ( variable que
servidorCPU = unIntel; // Conversion implicita solo almacena la direccin
servidorCPU.enMarchaCPU(); en RAM de un objeto ) que
unIntel.enMarchaCPU(); es una referencia annima a
un objeto. En el primer caso
a un objeto Amd y en el
segundo a un objeto Intel

Ver el cdigo completo en Casting0.java

Ferreiras Herencia en JAVA 111


En ambos casos, la referencia annima y
la referencia inicializada apuntan al mismo
objeto, en ese momento:
servidorCPU unAMD servidorCPU unIntel

Objeto Amd Objeto Intel

Lo cual implica que se podr usar cualquiera de ellas para


acceder a los miembros de dichos objetos. Por ejemplo:
servidorCPU. enMarchaCPU();
unAMD.enMarchaCPU();

Producir la misma salida


Ferreiras Herencia en JAVA 112
Obsrvese, en el segmento de cdigo
anterior, que:
servidorCPU = unAMD; // Conversion implicita

servidorCPU = unIntel; // Conversion implicita

Es posible hacerlo porque:

Las variables de referencia unAMD y unIntel ya haban sido previamente


inicializadas con las direcciones de objetos, esto es, ya almacenaban una
direccin de memoria RAM; y,

La conversin, en cada caso, es desde un objeto Derivado hacia un objeto


Base y, eso, es siempre posible. Porque un objeto de una Derivada
contendr toda la informacin correspondiente a la clase Base.

Ferreiras Herencia en JAVA 113


Observe ahora: Es importante recordar aqu que las
variables referencias no guardan
objetos, lo que almacenan son
referencias a la direccin de memoria
// Si intentamos
RAM ocupada por dichos objetos. Esto
es, en la declaracin:
unAMD = unCPU; // ERROR !!
NombreClase idVariable;
incompatible types
found : Cpu idVariable NO ES UN OBJETO, es
required: AmdCPU una referencia a un objeto de la clase
unAMD = unCPU; NombreClase.
^

Aunque ambas variables de referencia unAMD y unCPU


estn inicializadas, el error es porque se quiere convertir
un objeto Base - unCPU - a un objeto Derivado -
unAMD - y, eso, no es nunca posible.

Ferreiras Herencia en JAVA 114


upcasting ( Conversin hacia arriba ) Es
la conversin desde la clase Derivada
hacia la clase Base en la jerarqua de
herencia. Por ejemplo:
servidorCPU = unAMD; // Conversion implicita
servidorCPU = unIntel; // Conversion implicita

Siempre es posible y no se perder ninguna


informacin. Se ganarn los mtodos y las
variables definidos en la clase Derivada;

Ferreiras Herencia en JAVA 115


downcasting ( Conversin hacia abajo )
Es la conversin desde la clase Base
hacia la clase Derivada en la jerarqua de
herencia. Por ejemplo:
AmdCPU otroAMD = (AmdCPU) otroCPU;

No siempre es posible. Se recomienda usar el


operador java instanceof para hacer una prueba
logica y evitar el error ClassCastException en
tiempo de ejecucin.
Ver Casting0.java completo.

Ferreiras Herencia en JAVA 116


Casting explcito ( Conversin explcita )
Para usar objetos de la clase Base en lugares
donde objetos de la clase Derivada son
esperados se recomienda hacer un casting
explicito entre ellos: ( ClaseDestino ) variableReferenciaFuente;
Por ejemplo: Cpu otroCPU = (Cpu) unAMD; // Un upcasting

Cpu es la clase destino unAMD es la variable de referencia fuente

otroCPU es una referencia annima del objeto referenciado por unAMD y


ambas referencia el mismo objeto Cpu.
Un error se producir si se intenta llamar un mtodo que la clase destino
no tiene.

Ferreiras Herencia en JAVA 117


EJEMPLOS

Ferreiras Herencia en JAVA 118


EJERCICIOS

Ferreiras Herencia en JAVA 119


Referencias
1. Big Java, 4th Edition; Cay Horstmann; Wiley, 2010
2. Java Concepts, 6th Edition; Cay S. Horstmann, 2009
3. Java How to Program (early objects), 9th Edition; Paul Deitel
and Harvey Deitel; Prentice Hall, 2011

Ferreiras Herencia en JAVA 120


GRACIAS.

Ferreiras Herencia en JAVA 121

Potrebbero piacerti anche