Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

JSE M2 Herencia

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 20

Herencia

Índice Herencia
1 | Concepto de herencia en Java 3

2 | Constructores y herencia, la palabra super 5

3 | Sobrescribir métodos 7

4 | Métodos y datos protegidos en la herencia 9

5 | Clases abstractas 12

6 | Polimorfismo 14

7 | La utilización de final 15

8 | La clase Object 16
Herencia | TELEFÓNICA // 3

1. Concepto de herencia en Java


En Java la herencia se implementa con la palabra reservada extends, quizás la elección de esta
palabra fue con el propósito de enfatizar que las subclases (clases que heredan) son una extensión u
especialización de las superclases (clases de las que se hereda). Las superclases son una generalización
y las subclases una especialización.

Una subclase sólo puede tener un superclase y una superclase puede En Java la clase raíz de todas las clases es la clase Object y cuando
tener varias subclases, porque Java sólo implementa la herencia una clase no hereda explícitamente de ninguna otra, lo esta haciendo
simple. de Object.

La herencia es la implementación de la jerarquía de clases. https://docs.oracle.com/javase/8/docs/api/

superclase ClaseRaiz

Clase_A Clase_B

Clase_A_A Clase_B_B subclase

public class public class Clase_A extends public class Clase_A_A extends
ClaseRaiz{ ClaseRaiz{ Clase_A{
//datos //datos //datos FIGURA 6.2: OBJECT EN API JDK 8
//métodos //métodos //métodos
} } }

public class Clase_B extends public class Clase_A_B


ClaseRaiz{ extends Clase_A{
//datos //datos
//métodos //métodos
} }

FIGURA 6.1: JERARQUÍA DE CLASES, HERENCIA EN JAVA


Herencia | TELEFÓNICA // 4

Cuando se instala JDK 8, se pueden utilizar todas las clases de la Las subclases heredan las funciones miembro (métodos) de la
jerarquía de clases JSE 8, cuya documentación se puede consultar superclase, respetando el tipo de acceso. Por tanto a un objeto
en: instanciado de una subclase se le podrán invocar las funciones de la
parte pública de su propia clase y las de de la superclase.
Las subclases heredan las variables miembro (datos) de la
superclase, respetando el tipo de acceso. Por tanto un objeto
instanciado de una subclase ocupa el espacio de un objeto de la Pieza
superclase más el espacio especifico de las variables miembro Se heredan los
+ unir()
propias. métodos
+ cortar(int)

Pieza Tubo Plancha


Se heredan los datos - numero: int + unir() + unir()
- nombre:String + cortar(int) + cortar(int)
+ pulir()

Tubo Plancha
Acanalado Liso Todos los objetos Pieza, tienen
- calibre: float - largo: float las funcionalidades unir y cortar.
- medida: String - ancho: float + unir() + unir()
Cada tipo diferente de
- espesor: float + cortar(int) + cortar(int)
Pieza especializa esas dos
+ pintar(String) funcionalidades.
Cada tipo diferente de
Acanalado Liso pieza puede añadir otras
Un objeto Plancha es una
fucnionalidades diferentes
Pieza por tanto tiene numero,
- material: String - color: String
nombre, largo, ancho y
- esFlexible: boolean - espesor: float espesor
Un objeto Tubo Liso es una FIGURA 6.4: SE HEREDAN LOS MÉTODOS.
Pieza, por tanto tiene numero,
nombre, calibre, medida,
color y espesor

FIGURA 6.3: SE HEREDAN LOS DATOS.


Herencia | TELEFÓNICA // 5

2. Constructores y herencia, la palabra super


Cuando se crea un objeto de una subclase, el objeto se tiene que construir como un objeto de la
superclase. Esto se implementa utilizando la palabra super dentro de los constructores de las
subclases invocando a uno de los constructores de la superclase. Por tanto el orden de construcción
de los objetos de subclases es primero el constructor de la superclase, después el de la subclase. En
la jerarquía de las imágenes anteriores las clases con sus datos y un constructor por cada una de ellas
se muestra en el código siguiente:

public class Pieza { public class Plancha extends Pieza {


private int numero; private float largo;
private String nombre; private float ancho;
private float espesor;
public Pieza(int numero, String nombre) { public Plancha(int numero, String nombre,
super(); //constructor de float
Object, no hace falta largo, float ancho,
this.numero = numero; float espesor) {
this.nombre = nombre; super(numero, nombre); //constructor de
} Pieza
this.largo = largo;
} this.ancho = ancho;
this.espesor = espesor;
}
}
public class Tubo extends Pieza {
private float calibre;
private String medida;
public Tubo(int numero, String nombre,
Herencia | TELEFÓNICA // 6

float calibre, String material, boolean esFlexible) {


String medida) { super(numero, nombre, calibre, medida);
super(numero, nombre); //constructor de this.material = material;
Pieza this.esFlexible = esFlexible;
this.calibre = calibre; }
this.medida = medida; }
} public class Liso extends Tubo {
} private String color;
private float espesor;
public Liso(int numero, String nombre,
float calibre,
La forma de invocar a super tiene que estar de acuerdo con la forma
String medida,
de uno de los constructores de la superclase. A continuación también
String color, float
se muestran los códigos de las subclases que heredan de una de las
espesor) {
subclases, que para estas dos es su superclase.
super(numero, nombre, calibre, medida)
this.color = color;
this.espesor = espesor;
}
public class Acanalado extends Tubo {
}
private String material;
private boolean esFlexible;
public Acanalado(int numero, String
nombre,
float
calibre, String medida,

Herencia | TELEFÓNICA // 7

Las funciones también se heredan, esto quiere


decir que a cualquier objeto instanciado de public
static void main(String[] args) {
Pieza pieza = new Pieza(25, “Arandela centifugadora”);
una subclase se le pondrá invocar una de las Tubo tubo = new Tubo(101, “Especial”, 1.0f, “pulgadas”);
funcionalidades definidas en la superclase. Plancha plancha = new Plancha(201,”Extra”, 2.1f, 3.5f, 0.2f );
Acanalado acanalado = new Acanalado (102,”Humos”, 30.5f,”mms”,”plastico”, true);
Liso liso = new Liso (103, “Canal”, 11.2f,”mms”, “verde”,0.3F);
En las clases del ejemplo se ha definido la public class Pieza {
//datos
función toString en la superclase de todas las System.out.println(pieza);
//constructor
System.out.println(tubo);
demás clases. Se crean objetos de cada una public String toString() {
System.out.println(plancha);
de las clases y se invoca la función toString, return “Pieza [numero=” + numero + “, nombre=” +
System.out.println(acanalado);
nombre
ejecutándose el código de esta función System.out.println(liso);
+ “, clase=”+ this.getClass()+”]”;
}
definido en la superclase. }
}

FIGURA 6.5: EJECUCIÓN DE MÉTODO HEREDADO.

3. Sobrescribir métodos
Cuando se necesita que los objetos de las subclases tengan funcionalidades especializadas y distintas
de las heredadas, se definen esas funciones en dichas subclases. Este mecanismo se denomina
“override”, sobrescribir el funcionamiento del código heredado de los métodos de la superclase.
Para que exista “override” las funciones en la superclase y en las subclases tienen que tener
exactamente la misma forma: mismo nombre, mismo valor devuelto y misma lista de parámetros.
Herencia | TELEFÓNICA // 8

Dentro de la función sobrepasada en la subclase se invoca a esa


función o cualquier otra de la superclase con la palabra super. Un
ejemplo de “override” de métodos es el código siguiente: //Constructor
@Override
public String toString() {
return “Tubo [calibre=” + calibre + “,
medida=”
public class Plancha extends Pieza {
+ medida + “, “ + super.toString() +
private float largo;
“]”;
private float ancho;
}
private float espesor;
}
//constructor
public class Acanalado extends Tubo {
@Override
private String material;
public String toString() {
private boolean esFlexible;
return “Plancha [largo=” + largo + “,

ancho=” + ancho
//Constructor
+ “, espesor=” + espesor + “, “ + super.
@Override
toString()+ “]”;
public String toString() {
}
return “Acanalado [material=” + material
}
+ “, esFlexible=” + esFlexible + “, “ +
super.toString() + “]”;
public class Tubo extends Pieza {
}
private float calibre;
}
private String medida;

Herencia | TELEFÓNICA // 9

Un ejemplo de utilización de la función


toString sobrepasada es el que se muestra en public
static void main(String[] args) {
Pieza pieza = new Pieza(25, “Arandela centifugadora”);
la figura siguiente. Tubo tubo = new Tubo(101, “Especial”, 1.0f, “pulgadas”);
Plancha plancha = new Plancha(201,”Extra”, 2.1f, 3.5f, 0.2f );
Acanalado acanalado = newAcanalado
public class Acanaladoextends
(102,”Humos”,
Tubo { 30.5f,”mms”,”plastico”, true);
Liso liso = //datos
new Liso (103, “Canal”, 11.2f,”mms”, “verde”,0.3F);
//constructor
System.out.println(pieza);
@Override
System.out.println(tubo);
public String toString() {
System.out.println(plancha);
return “Acanalado [material=” + material + “,
esFlexible=”
System.out.println(acanalado);

System.out.println(liso); + esFlexible + “, “ + super.toString() + “]”;
} }
}

FIGURA 6.6: EJECUCIÓN DE MÉTODO SOBREPASADO.

4. Métodos y datos protegidos en la herencia


Para poder acceder a las variables y funciones miembro heredados de la superclase estos no pueden
estar en el ámbito private. Si se modifica su acceso a ámbito public o de paquete, en cierta manera se
estaría incumpliendo el principio de la ocultación y protección de las encapsulación.
Herencia | TELEFÓNICA // 10

Para mantener ese principio se implementa


el modificador de acceso protected. Cuando protected
Pieza
protected
un miembro de una superclase tiene ese
# numero: int
modificador puede ser accedido desde las private y accesible # nombre:String private y accesible
subclases que la hereden. en estas subclases
ese miembro es como si estuviera en ámbito
private para las que hereden de ellas. Tubo Plancha
- calibre: float - largo: float
- medida: String - ancho: float
- espesor: float

Acanalado Liso inaccesible


- material: String - color: String
- esFlexible: boolean - espesor: float

FIGURA 6.7: DATOS PROTECTED.


Herencia | TELEFÓNICA // 11

En la imagen se muestra una función de una


subclase que accede a datos protected de la Si no se utiliza el
public static void main(String[] args) { modificador protected, la
superclase. Plancha plancha = new Plancha(201,”Extra”, 25.4f, 3.5f,superclase
0.2f );tendría que
Random aleatorio = new Random(); proporcionar métodos
public de tipo “getter” para
Si no se utiliza el modificador protected, int metros=0;
obtener el valor de los
System.out.println(plancha);
la superclase tendría que proporcionar do{ datos private.
métodos public de tipo “getter” para obtener metros = aleatorio.nextInt(10)+1;
}while(plancha.cortar(metros));
el valor de los datos private. }
public class Plancha extends Pieza{
//datos
//constructor
//otras funciones
public boolean cortar(int metros){
DecimalFormat df = new
DecimalFormat(“#,###.##”);
System.out.println(“De “+ nombre +
“ con numero “ + numero);
if (largo < metros){
System.out.println(“ no se
pueden cortar “+ metros + “ metros “);
System.out.println(“ solo
quedan “+ df.format(largo) + “ metros “);
return false;
}
largo -= metros;
System.out.println(“ se han
cortado “+ metros + “ metros “);
System.out.println(“ quedan “+
df.format(largo) + “ metros “);
return true;
}
}

FIGURA 6.8: SUBCLASE ACCEDE A DATOS PROTECTED.


Herencia | TELEFÓNICA // 12

5. Clases abstractas
Si de una clase nunca se van a instanciar objetos, se denomina abstracta. Esto significa que dicha
clase define una representación (datos) y un comportamiento (métodos) comunes a las clases que
hereden de ella, los objetos serán instanciados de dichas clases, las cuales podrán especializar
las funcionalidades, sobrepasando los métodos y podrán añadir más atributos incorporando más
variables miembro.

En java las clases abstractas se implementan utilizando el En la jerarquía de clases utilizado la clase Pieza es abstracta,
modificador abstract. nunca habrá objetos que sean sólo Pieza, serán siempre objetos
instanciados de las clases Plancha o Tubo o Acanalado o Fijo. Si se
<<abstract>> Pieza califica Pieza como abstract esto implica que no se pueden crear
new Pieza( numero, nombre)
# numero: int
objetos de esta clase, pero hay que tener presente que cualquier
# nombre:String objeto de las subclases son objetos de tipo Pieza.

También se pueden definir métodos abstractos, esto implica que


Tubo Plancha no se implementa el código en dicho método, obligando que las
- calibre: float - largo: float
subclases que heredan lo implementen obligatoriamente.
- medida: String - ancho: float
- espesor: float En el código siguiente se califica un método como abstracto y se
Pieza p= new Tubo(numero, nombre, calibre, medida); sobrepasa obligatoriamente en las subclases.
// p referencia a Pieza numero
p
// un Tubo es una Pieza nombre
// con p sólo se puede alcanzar lo que esta en clase Pieza calibre
Tubo t = p; t
medida
//con t se puede alcanzar todo lo que esta en clase Tubo

FIGURA 6.9: CLASE ABSTRACTA.


Herencia | TELEFÓNICA // 13

public abstract class Pieza { }else{


protected int numero; System.out.println(“==== NO HAY
protected String nombre; MATERIAL =====”);
//constructor }
//otras funciones }
}
//función abstracta
abstract public void vender(int cantidad); public class Tubo extends Pieza {
} private float calibre;
private String medida;
public class Plancha extends Pieza { //Constructor
private float largo; //Otras funciones
private float ancho; @Override
private float espesor; public void vender(int cantidad) {
//Constructor System.out.println(“VENDIDO TUBO “+this.
//Otras funciones nombre);
@Override }
public void vender(int metros) { }
if( cortar(metros)){
System.out.println(“==== VENDIDO
=====”);
Herencia | TELEFÓNICA // 14

6. Polimorfismo
El polimorfismo se implementa cuando con un identificador de tipo superclase se referencia a un
objeto instanciado de una subclase y se invoca a una función que dicha subclase sobrepasa.

En el código siguiente:

public static void main(String[] args) {


Random aleatorio = new Random();
int metros = 0;
Pieza[] piezasvendidas = new Pieza[numVentas]; int numVentas = aleatorio.nextInt(5) + 1;
Pieza[] piezasvendidas = new
//Código que crea objetos Tubo y Plancha Pieza[numVentas];
//la referencia a cada uno de esos objetos es
//un elemento del array piezasvendidas for (int i = 0; i < piezasvendidas.length;
i++) {
for (Pieza pieza : piezasvendidas) { int tipoPieza = aleatorio.nextInt(3) +
int cantidad = aleatorio.nextInt(10) + 2;
1; if (tipoPieza % 2 == 0) {
pieza.vender(cantidad); piezasvendidas[i] =
} new Plancha(201, “Extra”,
30.f, 4.5f, 0.3f);
} else {
piezasvendidas[i] =
Se invoca la función vender con una referencia a la superclase Pieza, new Tubo(101, “Especial”,
1.0f, “pulgadas”);
pero en tiempo de compilación no se puede saber que vender será el }
que se ejecute. }

La forma pieza.vender(cantidad) es polimórfica, independientemente for (Pieza pieza : piezasvendidas) {


int cantidad = aleatorio.nextInt(10) +
de que la clase Pieza sea abstracta o no. El código del ejemplo siguiente 1;
muestra una aplicación del polimorfismo con esta jerarquía de clases. pieza.vender(cantidad);
}
Herencia | TELEFÓNICA // 15

7. La utilización de final
El modificador final tiene varias funcionalidades en Java, estas son:

• Aplicada a variables locales, de instancia o de clase, hace que • Aplicada a funciones de una superclase, implica que las subclases
no se puede modificar su valor una vez creada, son las llamadas no pueden sobrescribir dicha función. Esto es así para que
constantes. aquellas funcionalidades que no pueden cambiar en ninguna de
las clase que hereden la función final.
Ejemplos:
• Aplicada a una clase, implica que de esta clase no se puede
heredar, estas clases se suelen denominar “clase hoja” y
por contraposición la clase que esta en la parte superior de la
jerarquía se denomina “clase raíz”.
public class Ejemplo{
final public static int MAX_ELEMENTOS = 100; //
constante de clase

final private String mitipo = “Ejemplo”; //constante


de instancia

//otros datos de la clase


//constructores
//otras funciones
public void haceAlgo(){
final int numero=12; //constante local
//Código de la función
}

}
Herencia | TELEFÓNICA // 16

8. La clase Object
La clase Object es la raíz de la jerarquía
de clases del API JSE. Toda clase tiene package com.juan.piezas;
a Object como superclase. Por tanto public class PruebaObject {
todos los objetos, incluyendo los
arrays, pueden ejecutar los códigos de public static void main(String[] args) {
las funciones implementadas en esta Object objeto;
//Se puede utilizar una variable Object para referenciar cualquier tipo
clase. objeto = new Acanalado (102,”Humos”, 30.5f,”mms”,”plastico”, true);
System.out.println(“objeto es Acanalado: “+
(objeto instanceof Acanalado? “SI”:”NO”));
System.out.println(“La clase de objeto es: “+objeto.getClass());
Como todas las clases son subclases de objeto.
Object, cualquier variable de referencia a
Sólo se alcanzan
Object puede hacer referencia a un objeto funcionalidades
de cualquier clase. En la imagen siguiente de Object
se utiliza referencia Object para un objeto de
otra clase.

Acanalado tubo= (Acanalado) objeto; No todos los objetos son Acanalado,


tubo. por eso hay que moldear, así se pueden
} utilizar las funcionalidades de la clase
} específica

FIGURA 6.10: REFERENCIA A OBJECT.


Herencia | TELEFÓNICA / 17

Los métodos que define Object y están disponibles en todos los • Método hashCode: Cuando se sobrepasa este método hay que
objetos son los que se muestran en la tabla siguiente, algunos ya garantizar en lo posible que el entero que devuelve será diferente
han sido utilizados y comentados: para dos objetos distintos. Si dos objetos son iguales tendrían
que devolver el mismo entero.

Las definiciones de hashCode y equals tienen que ser compatibles,


Método Funcionalidad de tal forma que si x.equals(y) es true, entonces x.hashCode() e
Object clone() Crea un objeto idéntico al clonado. y.hashCode() tienen que retornar el mismo entero.
boolean equals(Object o) Devuelve true si los dos objetos son Los IDEs como Eclipse y NetBeans pueden generar
iguales. automáticamente el código tanto para equals y hashCode, que
void finalize() Se ejecuta instantes antes de liberar añada en el código las variables miembro del objeto que se
el espacio que ocupa el objeto. estimen oportunas para considerar la igualdad de dos objetos
Class<?> getClass() de la clase.
Retorna la clase a la que pertenece
el objeto.
int hashCode() Obtiene el código hash de un
objeto, el int que devuelve debe ser
diferente para cada objeto.
void notify() Reanuda la ejecución de un proceso.
void notifyAll() Reanuda la ejecución de todos los
procesos.
String toString() Retorna una cadena que
normalmente describe al objeto
void wait() El subproceso se pone en estado de
void wait(long milis) espera.
void wait(long milis,
int nanos)

Tabla 6.1: Métodos de Object.


Herencia | TELEFÓNICA // 18

Un código generado por eclipse para estos dos métodos • Método clone: Esta definido en el ámbito protected, por tanto
es el siguiente: habrá que definirlo en la clase que sea necesario, no se puede
invocar a un objeto esta funcionalidad protegida.

La función clone en todas sus definiciones (override) de todas las


clases tiene que retornar una referencia a Object. Por tanto habrá
@Override
public int hashCode() { que “moldear” hacer una conversión explicita al tipo concreto de
final int prime = 31; la clase del objeto clonado.
int result = 1;
result = prime * result +
((nombre == null) ? 0 :
Esta función lanza la excepción CloneNotSupportedException,
nombre.hashCode()); por tanto en las funciones que la utilicen o se captura la excepción
result = prime * result + numero; o se propaga, de momento hasta que se estudien las excepciones
return result; se propagara con throws CloneNotSupportedException.
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pieza other = (Pieza) obj;
if (nombre == null) {
if (other.nombre != null)
return false;
} else if (!nombre.equals(other.nombre))
return false;
if (numero != other.numero)
return false;
return true;
}
Herencia | TELEFÓNICA // 19

En el código siguiente se muestra un código


de la función clone y otro que prueba esta
funcionalidad. public class Liso extends Tubo {
private String color;
private float espesor;
public Liso(int numero, String nombre,
float calibre, String medida,
String color, float espesor) {
super(numero, nombre, calibre, medida);
this.color = color;
this.espesor = espesor;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new Liso(numero, nombre,
calibre, medida, color, espesor);
}
//Otras funciones
}
public static void main(String[] args)
throws
CloneNotSupportedException{

Liso liso = new Liso (103, “Canal”,
11.2f,”mms”, “verde”,0.3F);
Liso clonliso = (Liso) liso.clone();
if( liso == clonliso){
System.out.println(“No son clones”);
}
else{
System.out.println(“Son clones”);
System.out.println(liso);
System.out.println(clonliso);
}
}

También podría gustarte