0% encontró este documento útil (0 votos)
176 vistas38 páginas

Java: Constructores y Clases Avanzadas

1. El documento habla sobre constructores en Java y sus características como que tienen el mismo nombre de la clase, se ejecutan automáticamente y no retornan datos. Explica cómo crear un constructor para cargar los valores de un vector. 2. También cubre métodos comunes de la clase String como equals, length y substring. 3. Finalmente, proporciona ejercicios para practicar el uso de constructores y métodos de String.

Cargado por

forglow321
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
176 vistas38 páginas

Java: Constructores y Clases Avanzadas

1. El documento habla sobre constructores en Java y sus características como que tienen el mismo nombre de la clase, se ejecutan automáticamente y no retornan datos. Explica cómo crear un constructor para cargar los valores de un vector. 2. También cubre métodos comunes de la clase String como equals, length y substring. 3. Finalmente, proporciona ejercicios para practicar el uso de constructores y métodos de String.

Cargado por

forglow321
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Tema 7

CLASES AVANZADAS Y UTILIZACIÓN DE


OBJETOS
1. Librerías y paquetes en Java

1
2. Constructores
En Java podemos definir un método que se ejecute inicialmente y en forma automática.
Este método se lo llama constructor.

El constructor tiene las siguientes características:

• Tiene el mismo nombre de la clase.


• Es el primer método que se ejecuta.
• Se ejecuta en forma automática.
• No puede retornar datos.
• Se ejecuta una única vez.
• Un constructor tiene por objetivo inicializar atributos.

Ejemplo:

Se desea guardar los sueldos de 5 operarios en un vector. Realizar la creación y carga


del vector en el constructor.

import [Link];
public class Operarios {
private Scanner teclado;
private int[] sueldos;

public Operarios()
{
teclado=new Scanner([Link]);
sueldos=new int[5];
for(int f=0;f<5;f++) {
[Link]("Ingrese valor de la componente:");
sueldos[f]=[Link]();
}
}

public void imprimir() {


for(int f=0;f<5;f++) {
[Link](sueldos[f]);
}
}

public static void main(String[] ar) {


Operarios op=new Operarios();
[Link]();
}
}

Como podemos ver es el mismo problema que resolvimos cuando vimos vectores. La
diferencia es que hemos sustituido el método cargar con el constructor:

public Operarios()
{
teclado=new Scanner([Link]);
sueldos=new int[5];
for(int f=0;f<5;f++) {
[Link]("Ingrese valor de la componente:");

2
sueldos[f]=[Link]();
}
}

Como la clase se llama Operarios el constructor tiene el mismo nombre, no disponemos


la palabra clave void ya que el constructor no puede retornar datos.

La ventaja de plantear un constructor en lugar de definir un método con cualquier


nombre es que se llamará en forma automática cuando se crea un objeto de esta clase:

public static void main(String[] ar) {


Operarios op=new Operarios();

Cuando se crea el objeto op se llama al método constructor.

Finalmente llamamos al método imprimir:

[Link]();

Ejercicios

7.1. Plantear una clase llamada Alumno y definir como atributos su nombre y su edad. En
el constructor realizar la carga de datos. Definir otros dos métodos para imprimir los datos
ingresados y un mensaje si es mayor o no de edad (edad >=18)

7.2. Plantear una clase TablaMultiplicar. Definir dos constructores uno con un parámetro
que llegue un entero indicando que tabla queremos ver y otro con dos enteros que indique
el primero que tabla queremos ver y el segundo parámetro indica cuantos términos
mostrar.

7.3. Confeccionar una clase que represente un empleado. Definir como atributos su
nombre y su sueldo. En el constructor cargar los atributos y luego en otro método
imprimir sus datos y por último uno que imprima un mensaje si debe pagar impuestos (si
el sueldo supera a 3000)

7.4. Implementar la clase operaciones. Se deben cargar dos valores enteros en el


constructor, calcular su suma, resta, multiplicación y división, cada una en un método,
imprimir dichos resultados.

3. La clase String
Manipular cadenas de caracteres en Java es bastante simple, pues el lenguaje nos
proporciona clases específicas para trabajar con ellas y lo hacemos a través de los métodos
que poseen cada clase.

La API de Java posee varias clases para la manipulación de cadenas y caracteres, la más
conocida es la clase String.

3
Un objeto del tipo String es un Array que representa una cadena alfanumérica que
contiene un valor constante y NO se puede modificar luego de creado.

Cuando trabajamos con cadenas de texto muchas veces precisamos manipularlas,


modificarlas, buscar y extraer una subcadena, sacar informes, convertir a mayúsculas o
minúsculas, entre otras muchas cosas.

Con el método String en Java podemos obtener la ubicación de una letra dentro de la
cadena, la longitud que tiene un grupo de caracteres, una porción de una cadena o palabra,
ordenarlas de menor a mayor y viceversa, y muchas otras tareas.

Para poder realizar todas estas acciones Java nos ofrece una buena cantidad de métodos
para esta clase.

Métodos de la clase String en Java

Los métodos predeterminados que posee String nos dan la posibilidad de realizar
muchas cosas, aquí presentamos algunos de ellos:

• boolean equals(String s1)


Retorna true si el contenido de caracteres del parámetro s1 es exactamente igual
a la cadena de caracteres del objeto que llama al método equals.
• boolean equalsIgnoreCase(String s1)
El funcionamiento es casi exactamente igual que el método equals con la
diferencia que no tiene en cuenta mayúsculas y minúsculas (si comparamos
'Ana' y 'ana' luego el método equalsIgnoreCase retorna true)
• int compareTo(String s1)
Este método retorna un 0 si el contenido de s1 es exactamente igual al String
contenido por el objeto que llama al método compareTo. Retorna un valor >0 si
el contenido del String que llama al método compareTo es mayor
alfabéticamente al parámetro s1.
• char charAt(int pos)
Retorna un caracter del String, llega al método la posición del caracter a extraer.
• int length()
Retorna la cantidad de caracteres almacenados en el String.
• String substring(int pos1,int pos2)
Retorna un substring a partir de la posición indicada en el parámetro pos1 hasta
la posición pos2 sin incluir dicha posición.
• int indexOf(String s1)
Retorna -1 si el String que le pasamos como parámetro no está contenida en la
cadena del objeto que llama al método. En caso que se encuentre contenido el
String s1 retorna la posición donde comienza a repetirse.
• String toUpperCase()
Retorna un String con el contenido convertido todo a mayúsculas.
• String toLowerCase()
Retorna un String con el contenido convertido todo a minúsculas.

4
5
6
Ejemplo

Confeccionar una clase que solicite el ingreso de dos String y luego emplee los métodos
más comunes de la clase String.

import [Link];
public class Cadena1 {
public static void main(String[] ar) {
Scanner teclado=new Scanner([Link]);
String cad1;
String cad2;
[Link]("Ingrese la primer cadena:");
cad1=[Link]();
[Link]("Ingrese la segunda cadena:");
cad2=[Link]();
if ([Link](cad2)==true) {
[Link](cad1+" es exactamente igual a "+cad2);
} else {
[Link](cad1+" no es exactamente igual a
"+cad2);
}
if ([Link](cad2)==true) {
[Link](cad1+" es igual a "+cad2+" sin tener en
cuenta mayúsculas/minúsculas");
} else {
[Link](cad1+" no es igual a "+cad2+" sin tener
en cuenta mayúsculas/minúsculas");
}
if ([Link](cad2)==0) {
[Link](cad1+" es exactamente igual a "+cad2);
} else {
if ([Link](cad2)>0) {
[Link](cad1+ " es mayor alfabéticamente
que "+cad2);
} else {
[Link](cad2+ " es mayor alfabéticamente
que "+cad1);
}
}
char carac1=[Link](0);
[Link]("El primer caracter de "+cad1+" es
"+carac1);
int largo=[Link]();
[Link]("El largo del String "+cad1+" es "+largo);
String cad3=[Link](0,3);
[Link]("Los primeros tres caracteres de "+cad1+"
son "+cad3);
int posi=[Link](cad2);
if (posi==-1) {
[Link](cad2+" no está contenido en "+cad1);
} else {
[Link](cad2+" está contenido en "+cad1+" a
partir de la posición "+posi);
}
[Link](cad1+ " convertido a mayúsculas es
"+[Link]());
[Link](cad1+ " convertido a minúsculas es
"+[Link]());
}
}

7
Ejercicios

7.5. Realizar una clase, que permita cargar una dirección de mail en el constructor, luego
en otro método mostrar un mensaje si contiene el carácter '@'.

7.6. Cargar un String por teclado e implementar los siguientes métodos:

a) Imprimir la primera mitad de los caracteres de la cadena.


b) Imprimir el último carácter.
c) Imprimirlo en forma inversa.
d) Imprimir cada carácter del String separado con un guion.
e) Imprimir la cantidad de vocales almacenadas.
f) Implementar un método que verifique si la cadena se lee igual de izquierda a
derecha tanto como de derecha a izquierda.

7.7. Desarrollar un programa que solicite la carga de una clave. La clase debe tener dos
métodos uno para la carga y otro que muestre si la clave es la correcta (la clave a comparar
es "123abc")

7.8. Confeccionar un programa que permita cargar los nombres de 5 personas y sus mail,
luego implementar los siguientes métodos:

a) Mostrar por pantalla los datos.


b) Consulta del mail ingresando su nombre.
c) Mostrar los mail que no tienen el carácter @.

7.9. Codifique un programa que permita cargar una oración por teclado, luego mostrar
cada palabra ingresada en una línea distinta.

4. Colaboración entre clases


Normalmente un problema resuelto con la metodología de programación orientada a
objetos no interviene una sola clase, sino que hay muchas clases que interactúan y se
comunican.

Plantearemos un problema separando las actividades en dos clases.

Ejemplo 3

Un banco tiene 3 clientes que pueden hacer depósitos y extracciones. También el banco
requiere que al final del día calcule la cantidad de dinero que hay depositada.

Lo primero que hacemos es identificar las clases:

Podemos identificar la clase Cliente y la clase Banco.

Luego debemos definir los atributos y los métodos de cada clase:

8
Cliente
atributos
nombre
montante
métodos
constructor
depositar
extraer
retornarMontante

Banco
atributos
3 Cliente (3 objetos de la clase Cliente)
métodos
constructor
operar
depositosTotales

Creamos un proyecto Proyecto1 y dentro del proyecto creamos dos clases llamadas:
Cliente y Banco.

public class Cliente {


private String nombre;
private int montante;

public Cliente(String nom) {


nombre=nom;
montante=0;
}

public void depositar(int m) {


montante=montante+m;
}

public void extraer(int m) {


montante=montante-m;
}

public int retornarMontante() {


return montante;
}

public void imprimir() {


[Link](nombre+" tiene depositado la suma de
"+montante);
}
}

public class Banco {


private Cliente cliente1,cliente2,cliente3;

public Banco() {
cliente1=new Cliente("Juan");
cliente2=new Cliente("Ana");
cliente3=new Cliente("Pedro");
}

public void operar() {

9
[Link] (100);
[Link] (150);
[Link] (200);
[Link] (150);
}

public void depositosTotales ()


{
int t = [Link] () +
[Link] () + [Link] ();
[Link] ("El total de dinero en el banco es:" + t);
[Link]();
[Link]();
[Link]();
}

public static void main(String[] ar) {


Banco banco1=new Banco();
[Link]();
[Link]();
}
}

Analicemos la implementación del problema.

Los atributos de una clase normalmente son privados para que no se tenga acceso
directamente desde otra clase, los atributos son modificados por los métodos de la
misma clase:

private String nombre;


private int montante;

El constructor recibe como parámetro el nombre del cliente y lo almacena en el atributo


respectivo e inicializa el atributo montante en cero:

public Cliente(String nom) {


nombre=nom;
montante=0;
}

Los métodos depositar y extraer actualizan el atributo montante con el dinero que llega
como parámetro (para simplificar el problema no hemos validado que cuando se extrae
dinero el atributo montante quede con un valor negativo):

public void depositar(int m) {


montante=montante+m;
}

public void extraer(int m) {


montante=montante-m;
}

El método retornarMontante tiene por objetivo comunicar al Banco la cantidad de


dinero que tiene el cliente (recordemos que como el atributo montante es privado de la
clase, debemos tener un método que lo retorne):

public int retornarMontante() {

10
return montante;
}

Por último el método imprimir muestra nombre y el montante de dinero del cliente:

public void imprimir() {


[Link](nombre+" tiene depositado la suma de
"+montante);
}

Como podemos observar la clase Cliente no tiene función main. Entonces donde
definimos objetos de la clase Cliente?
La respuesta a esta pregunta es que en la clase Banco definimos tres objetos de la clase
Cliente.

Veamos ahora la clase Banco que requiere la colaboración de la clase Cliente.


Primero definimos tres atributos de tipo Cliente:

public class Banco {


private Cliente cliente1,cliente2,cliente3;

En le constructor creamos los tres objetos (cada vez que creamos un objeto de la clase
Cliente debemos pasar a su constructor el nombre del cliente, recordemos que su
montante de depósito se inicializa con cero):

public Banco() {
cliente1=new Cliente("Juan");
cliente2=new Cliente("Ana");
cliente3=new Cliente("Pedro");
}

El método operar del banco (llamamos a los métodos depositar y extraer de los
clientes):

public void operar() {


[Link] (100);
[Link] (150);
[Link] (200);
[Link] (150);
}

El método depositosTotales obtiene el montante depositado de cada uno de los tres


clientes, procede a mostrarlos y llama al método imprimir de cada cliente para poder
mostrar el nombre y depósito:

public void depositosTotales ()


{
int t = [Link] () +
[Link] () + [Link] ();
[Link] ("El total de dinero en el banco es:" + t);
[Link]();
[Link]();
[Link]();

11
}

Por último, en la main definimos un objeto de la clase Banco (la clase Banco es la clase
principal en nuestro problema):

public static void main(String[] ar) {


Banco banco1=new Banco();
[Link]();
[Link]();
}

Ejercicios

7.10. Plantear un programa que permita jugar a los dados. Las reglas de juego son: se
tiran tres dados si los tres salen con el mismo valor mostrar un mensaje que "gano", sino
"perdió".

Lo primero que hacemos es identificar las clases:

Podemos identificar la clase Dado y la clase JuegoDeDados.

Luego los atributos y los métodos de cada clase:

Dado
atributos
valor
métodos
tirar
imprimir
retornarValor

JuegoDeDados
atributos
3 Dado (3 objetos de la clase Dado)
métodos
constructor
jugar

Creamos un proyecto Proyecto2 y dentro del proyecto creamos dos clases llamadas:
Dado y JuegoDeDados.

7.11. Plantear una clase Club y otra clase Socio.


La clase Socio debe tener los siguientes atributos privados: nombre y la antigüedad en
el club (en años). En el constructor pedir la carga del nombre y su antigüedad. La clase
Club debe tener como atributos 3 objetos de la clase Socio. Definir una responsabilidad
para imprimir el nombre del socio con mayor antigüedad en el club.

12
5. Sobrecarga de métodos y constructores
Se le llama sobrecarga de funciones o métodos a la creación de varias funciones dentro
de nuestro programa, que tienen el mismo nombre, pero sus argumentos son distintos y
realizan distinta acción.

Básicamente sobrecargar significa definir nuevos métodos con parámetros distintos para
ampliar las funcionalidades del método original, manteniendo la calidad en el código,
reutilizando las funciones, sin extender la cantidad de líneas en nuestro programa.

Es posible porque Java nos permite utilizar la sobrecarga, y la ventaja principal de esta es
la flexibilidad a la hora de usar un método ya creado, pero con diferente tipo de datos,
para obtener otro resultado.

Dependiendo de los tipos y la cantidad de argumentos, Java puede identificar cuál de los
métodos existentes debe utilizar.

Esto significa que para sobrecargar una función o método, al llamarla debemos cambiar
el tipo y / o número de argumentos, este proceso se conoce como method overloading.

La importancia de la sobrecarga radica en poder relacionar los métodos a través de un


nombre común, aunque cumplan distintas funciones.

A veces es necesario inicializar un objeto de diferentes formas. Para ello, se realiza la


sobrecarga de constructores. Los constructores sobrecargados deben tener diferente
número o tipo de parámetros. Cada constructor realiza una tarea diferente.

Se puede utilizar la palabra reservada this para llamar a un constructor desde otro. La llamada this
debe ser la primera línea de dicho constructor.

Ejemplo Sobrecarga de métodos

Realizar un programa en Java que permita calcular el pedido que realiza un cliente en un
restaurante.

Los pedidos de un restaurante están conformados por las siguientes partes:


Un primer plato.
Un segundo plato.
Una bebida.
Un postre.

Cada uno de dichas partes tiene un nombre y un valor. Se requiere definir métodos
sobrecargados para calcular el valor del pedido dependiendo si el cliente solicita:
Un primer plato y una bebida.
Un primer plato, un segundo plato y una bebida.
Un primer plato, un segundo plato, una bebida y un postre.

Implementar un método main que utilice los tres métodos sobrecargados en tres
diferentes pedidos.

13
public class Pedido {
public void calcularPedido(String primerPlato, double
costoPrimerPlato, String bebida, double costoBebida) {
double total = costoPrimerPlato + costoBebida;
[Link]("El costo de " + primerPlato + " y " + bebida +
" es = $" + total);
}
public void calcularPedido(String primerPlato, double
costoPrimerPlato, String segundoPlato, double costoSegundoPlato,
String bebida, double costoBebida) {
double total = costoPrimerPlato + costoSegundoPlato +costoBebida;
[Link]("El costo de " + primerPlato + " el del segundo
" + segundoPlato + " y bebida " + bebida + " es = $" + total);
}
public void calcularPedido(String primerPlato, double
costoPrimerPlato, String segundoPlato, double costoSegundoPlato,
String postre, double costoPostre, String bebida, double costoBebida)
{
double total = costoPrimerPlato + costoSegundoPlato + costoBebida
+ costoPostre;
[Link]("El costo de " + primerPlato + " + " +
segundoPlato + " + " + bebida + " + " + postre + " es = $" + total);
}
}

public class Main {

public static void main(String[] args) {


Pedido pedido1 = new Pedido();
[Link]("Ensalada", 5, "Gaseosa", 2);
Pedido pedido2 = new Pedido();
[Link]("Crema de verduras", 5, "Churrasco",
12, "Gaseosa", 2);
Pedido pedido3 = new Pedido();
[Link]("Crema de espinacas",
5,"Salmón",10,"Tiramisú",5,"Gaseosa", 2);
}

Ejercicios

7.12. Definir una clase denominada Suma, la cual tiene varios métodos sumar
sobrecargados:
• Un método sumar que obtiene la suma de dos valores enteros pasados como
parámetros.
• Un método sumar que obtiene la suma de tres valores enteros pasados como
parámetros.
• Un método sumar que obtiene la suma de dos valores double pasados como
parámetros.
• Un método sumar que obtiene la suma de tres valores double pasados como
parámetros.

14
Ejemplo 6 Sobrecarga de constructores
Realizar un programa en Java que permita modelar un artículo científico. Los artículos
científicos contienen los siguientes metadatos: nombre del artículo, autor, palabras claves,
nombre de la publicación, año y resumen.

Se deben definir tres constructores sobrecargados:


El primero inicializa un artículo científico con solo su título y autor.
El segundo constructor, un artículo científico con su nombre, autor, palabras
claves, nombre de la publicación y año. Debe invocar al primer constructor.
El tercer constructor, un artículo científico con su nombre, autor, palabras
claves, nombre de la publicación, año y resumen. Debe invocar al segundo
constructor.

Se requiere un método que imprima los atributos de un artículo en pantalla. Realizar un


método main que utilice el tercer constructor para instanciar un artículo científico e
imprima los valores de sus atributos en pantalla.

Ejercicios

7.13. Definir una clase Empleado que tiene como atributos: identificador, nombre,
apellidos y edad del empleado. La clase contiene dos constructores:

• El primer constructor no tiene parámetros e inicializa los atributos del objeto con los
siguientes valores: identificador del empleado con el valor 100, el nombre con “Nuevo
empleado”, apellidos con “Nuevo empleado” y edad del empleado con 18.
• El segundo constructor asigna valores a los atributos de acuerdo con los valores
pasados como parámetros.

6. Herencia
Vimos en el concepto anterior que dos clases pueden estar relacionadas por la
colaboración. Ahora veremos otro tipo de relaciones entre clases que es la Herencia.

La herencia significa que se pueden crear nuevas clases partiendo de clases existentes,
que tendrá todas los atributos y los métodos de su 'superclase' o 'clase padre' y además
se le podrán añadir otros atributos y métodos propios.

clase padre

Clase de la que desciende o deriva una clase. Las clases hijas (descendientes) heredan
(incorporan) automáticamente los atributos y métodos de la la clase padre.

Subclase

15
Clase desciendiente de otra. Hereda automáticamente los atributos y métodos de su
superclase. Es una especialización de otra clase. Admiten la definición de nuevos
atributos y métodos para aumentar la especialización de la clase.

Veamos algunos ejemplos teóricos de herencia:

1) Imaginemos la clase Vehículo. Qué clases podrían derivar de ella?

Vehiculo

Colectivo Moto Auto

Ford Renault

Siempre hacia abajo en la jerarquía hay una especialización (las subclases añaden
nuevos atributos y métodos.

2) Imaginemos la clase Software. ¿Qué clases podrían derivar de ella?

Software

Aplicacion Base

ProcesadorTexto PlanillaDeCalculo S. Operativo

Word WordPerfect Excel Lotus Linux Windows

El primer tipo de relación que habíamos visto entre dos clases, es la de colaboración.
Recordemos que es cuando una clase contiene un objeto de otra clase como atributo.
Cuando la relación entre dos clases es del tipo "...tiene un..." o "...es parte de...", no
debemos implementar herencia. Estamos frente a una relación de colaboración de clases
no de herencia.

Si tenemos una ClaseA y otra ClaseB y notamos que entre ellas existe una relación de
tipo "... tiene un...", no debe implementarse herencia sino declarar en la clase ClaseA un
atributo de la clase ClaseB.

Por ejemplo: tenemos una clase Auto, una clase Rueda y una clase Volante. Vemos que
la relación entre ellas es: Auto "...tiene 4..." Rueda, Volante "...es parte de..." Auto; pero
la clase Auto no debe derivar de Rueda ni Volante de Auto porque la relación no es de
tipo-subtipo sino de colaboración. Debemos declarar en la clase Auto 4 atributos de tipo
Rueda y 1 de tipo Volante.

Luego si vemos que dos clase responden a la pregunta ClaseA "..es un.." ClaseB es
posible que haya una relación de herencia.

Por ejemplo:

Auto "es un" Vehiculo


Circulo "es una" Figura
Mouse "es un" DispositivoEntrada
Suma "es una" Operacion

16
Ejemplo

Supongamos que necesitamos implementar dos clases que llamaremos Suma y Resta.
Cada clase tiene como atributo valor1, valor2 y resultado. Los métodos para definir son
cargar1 (que inicializa el atributo valor1), carga2 (que inicializa el atributo valor2),
operar (que en el caso de la clase "Suma" suma los dos atributos y en el caso de la clase
"Resta" hace la diferencia entre valor1 y valor2, y otro método mostrarResultado.

Si analizamos ambas clases encontramos que muchos atributos y métodos son idénticos.
En estos casos es bueno definir una clase padre que agrupe dichos atributos y
responsabilidades comunes.

La relación de herencia que podemos disponer para este problema es:

Operacion

Suma Resta
Solamente el método operar es distinto para las clases Suma y Resta (esto hace que no
lo podamos disponer en la clase Operacion), luego los métodos cargar1, cargar2 y
mostrarResultado son idénticos a las dos clases, esto hace que podamos disponerlos en
la clase Operacion. Lo mismo los atributos valor1, valor2 y resultado se definirán en la
clase padre Operacion.

Crear un proyecto y luego crear cuatro clases llamadas: Operacion, Suma, Resta y
Prueba

import [Link];
public class Operacion {
protected Scanner teclado;
protected int valor1;
protected int valor2;
protected int resultado;

public Operacion() {
teclado=new Scanner([Link]);
}

public void cargar1() {


[Link]("Ingrese el primer valor:");
valor1=[Link]();
}

public void cargar2() {


[Link]("Ingrese el segundo valor:");
valor2=[Link]();
}

public void mostrarResultado() {


[Link](resultado);
}
}

public class Suma extends Operacion{


void operar() {
resultado=valor1+valor2;
}

17
}

public class Resta extends Operacion {


public void operar(){
resultado=valor1-valor2;
}
}

public class Prueba {


public static void main(String[] ar) {
Suma suma1=new Suma();
suma1.cargar1();
suma1.cargar2();
[Link]();
[Link]("El resultado de la suma es:");
[Link]();
Resta resta1=new Resta();
resta1.cargar1();
resta1.cargar2();
[Link]();
[Link]("El resultado de la resta es:");
[Link]();
}
}

La clase Operación define los cuatro atributos:

import [Link];
public class Operacion {
protected Scanner teclado;
protected int valor1;
protected int valor2;
protected int resultado;

Ya veremos que definimos los atributos con este nuevo modificador de acceso
(protected) para que la subclase tenga acceso a dichos atributos. Si los definimos private
las subclases no pueden acceder a dichos atributos.

Los métodos de la clase Operacion son:

public Operacion() {
teclado=new Scanner([Link]);
}

public void cargar1() {


[Link]("Ingrese el primer valor:");
valor1=[Link]();
}

public void cargar2() {


[Link]("Ingrese el segundo valor:");
valor2=[Link]();
}

public void mostrarResultado() {


[Link](resultado);
}

18
Ahora veamos como es la sintaxis para indicar que una clase hereda de otra:

public class Suma extends Operacion{

Utilizamos la palabra clave extends y seguidamente el nombre de la clase padre (con


esto estamos indicando que todos los métodos y atributos de la clase Operación son
también métodos de la clase Suma.

Luego la característica que añade la clase Suma es el siguiente método:

void operar() {
resultado=valor1+valor2;
}

El método operar puede acceder a los atributos heredados (siempre y cuando los
mismos se declaren protected, en caso que sean private si bien lo hereda de la clase
padre solo los pueden modificar métodos de dicha clase padre.

Ahora podemos decir que la clase Suma tiene cinco métodos (cuatro heredados y uno
propio) y 3 atributos (todos heredados)

Luego en otra clase creamos un objeto de la clase Suma:

public class Prueba {


public static void main(String[] ar) {
Suma suma1=new Suma();
suma1.cargar1();
suma1.cargar2();
[Link]();
[Link]("El resultado de la suma es:");
[Link]();
Resta resta1=new Resta();
resta1.cargar1();
resta1.cargar2();
[Link]();
[Link]("El resultado de la resta es:");
[Link]();
}
}

Podemos llamar tanto al método propio de la clase Suma "operar()" como a los métodos
heredados. Quien utilice la clase Suma solo debe conocer que métodos públicos tiene
(independientemente que pertenezcan a la clase Suma o a una clase superior)

La lógica es similar para declarar la clase Resta.

La clase Operación agrupa en este caso un conjunto de atributos y métodos comunes a


un conjunto de subclases (Suma, Resta). No tiene sentido definir objetos de la clase
Operacion.

El planteo de jerarquías de clases es una tarea compleja que requiere un perfecto


entendimiento de todas las clases que intervienen en un problema, cuales son sus
atributos y responsabilidades.

19
Ejercicios

7.14. Confeccionar una clase Persona que tenga como atributos el nombre y la edad.
Definir como responsabilidades un método que cargue los datos personales y otro que
los imprima.
Plantear una segunda clase Empleado que herede de la clase Persona. Añadir un atributo
sueldo y los métodos de cargar el sueldo e imprimir su sueldo.
Definir un objeto de la clase Persona y llamar a sus métodos. También crear un objeto
de la clase Empleado y llamar a sus métodos.

7.15. La empresa informática “IPM Tech” necesita llevar un registro de todos sus
empleados que se encuentran en la oficina central, para eso ha creado un diagrama de
clases que debe incluir lo siguiente:

• Empleado

Atributos:
- nombre: tipo cadena (Debe ser nombre y apellido)
- cedula: tipo cadena
- edad : entero (Rango entre 18 y 45 años)
- casado: boolean
- salario: tipo numérico doble

Métodos:
- Constructor con y sin parámetros de entrada
- Método que permita mostrar la clasificación según la edad de acuerdo al
siguiente algoritmo: Si edad es menor o igual a 21, Principiante. Si edad es
>=22 y <=35, Intermedio. Si edad es >35, Senior.
- Imprimir los datos del empleado por pantalla (utilizar salto de línea \n para
separar los atributos.
- Un método que permita aumentar el salario en un porcentaje que sería pasado
como parámetro al método.

• Programador (Especialización de Empleado). Clase que hereda de Empleado


todos los atributos y métodos.

Atributos:
- lineasDeCodigoPorHora : tipo entero
- lenguajeDominante: tipo cadena

Metodos:
- Constructor con y sin parámetros de entrada.

Declaración y definición de relaciones de herencia

20
21
7. Enumerados
Los enum en Java, llamados también enumeraciones o listado específico, se refieren a la
herramienta que permite representar conjuntos de constantes con un nombre en el
lenguaje de programación.

Estas enumeraciones se utilizan cuando se tiene conocimiento completo con respecto de


los valores posibles en tipo de compilación, como pueden ser las opciones en un menú y
demás.

22
Ejemplo

public enum Operaciones {


SUMA, RESTA, MULTIPLICACION, DIVISION
}

public class PruebaEnum {


public static void main(String[] args) {
int valor1 = 10;
int valor2 = 20;
Operaciones operacion;
operacion=[Link];
if (operacion == [Link]) {
int resta = valor1 - valor2;
[Link](resta);
}
operacion=[Link];
if (operacion == [Link]) {
int suma = valor1 + valor2;
[Link](suma);
}
}
}

Escriba un programa que defina un enumerado para los días de la semana. En el programa
defina una variable del enumerado y asígnele el valor del día que corresponde al martes.
A continuación, escriba por pantalla dicha variable y escriba el valor del enumerado
correspondiente al domingo.

public class Enumerados

public enum DíasSemana {


LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO
}

public static void main(String[] args) {


DíasSemana unDía = Dí[Link];
[Link]("El día elegido es:"+ unDía);
[Link]("El último día de la semana es:"+Dí[Link]);
}
}

Escriba un enumerado para los tipos de lavado de un túnel de lavado que guarde la
información de los tiempos. Los tipos de lavado son básico, normal y super y el tiempo
que se tarda en cada uno es de 3, 5 y 8 minutos, respectivamente. Escriba un programa
que muestre su funcionamiento.

enum Tipolavado{BASIC0(3), NORMAL(5), SUPER(8);


private int tiempo;
Tipolavado(int tiempo){
[Link] = tiempo;
}

public int tiempo(){

23
return tiempo;
}
}

public class Tunellavado{


public static void main(String[] args){
Tipolavado lavadoSuper = [Link];
[Link]("El lavado"+lavadoSuper +"tarda"+ [Link]());
}
}

8. Clases abstractas en java.


En Java se dice que son clases abstractas aquellas clases base (superclases) de las que no
se permite la creación de objetos. Para ello, se utiliza la palabra clave abstract.

Métodos abstractos

En una clase abstracta es posible definir métodos abstractos, los cuales se caracterizan
por el hecho de que no pueden ser implementados en la clase base. De ellos, solo se
escribe su signatura en la superclase, y su funcionalidad –polimórfica– tiene que indicarse
en las clases derivadas (subclases).

Ejemplo

Dadas la siguientes clases (Figura, Cuadrado y Triangulo):

public abstract class Figura


{
private String color;

public Figura(String color)


{
[Link] = color;
}

public abstract double calcularArea();

public String getColor()


{
return color;
}
}

En la clase Figura se ha definido un atributo (color), un constructor y dos métodos


(calcularArea y getColor).

public class Cuadrado extends Figura


{
private double lado;

public Cuadrado(String color, double lado)


{

24
super(color);
[Link] = lado;
}

public double calcularArea()


{
return lado * lado;
}
}

En la clase Cuadrado se ha definido un atributo (lado), un constructor y un método


(calcularArea).

public class Triangulo extends Figura


{
private double base;
private double altura;

public Triangulo(String color, double base, double altura)


{
super(color);
[Link] = base;
[Link] = altura;
}

public double calcularArea()


{
return (base * altura) / 2;
}
}

En la clase Triangulo se han definido dos atributos (base y altura), un constructor y un


método (calcularArea).

Como se puede observar, el método calcularArea ha sido definido abstracto (abstract)


en la superclase abstracta Figura, indicándose solamente su signatura:

public abstract double calcularArea();

Por otro lado, véase que, en cada una de las subclases (Cuadrado y Triangulo) se ha
implementado dicho método.

Ejemplo { PruebaCuadrado } Al compilar y ejecutar el siguiente código:

import [Link];

public class PruebaCuadrado


{
public static void main(String[] args)
{
String colorDelCuadrado;
double ladoDelCuadrado;

Scanner teclado = new Scanner([Link]);

[Link]("Introduzca el color del cuadrado: ");

25
colorDelCuadrado = [Link]();

[Link]("Introduzca el lado del cuadrado: ");


ladoDelCuadrado = [Link]();

Cuadrado cuadrado1 = new Cuadrado(colorDelCuadrado,


ladoDelCuadrado);

[Link]("El área del cuadrado %s es: %f",


[Link](), [Link]());
}
}

Ejemplo { PruebaTriangulo } Al compilar y ejecutar:

import [Link];

public class PruebaTriangulo


{
public static void main(String[] args)
{
String colorDelTriangulo;
double baseDelTriangulo;
double alturaDelTriangulo;

Scanner teclado = new Scanner([Link]);

[Link]("Introduzca el color del triángulo: ");


colorDelTriangulo = [Link]();

[Link]("Introduzca la base del triángulo: ");


baseDelTriangulo = [Link]();

[Link]("Introduzca la altura del triángulo: ");


alturaDelTriangulo = [Link]();

Triangulo triangulo1 = new Triangulo(colorDelTriangulo,


baseDelTriangulo, alturaDelTriangulo);

[Link]("El área del triángulo %s es: %f",


[Link](), [Link]());
}
}

Ejercicios

7.16. Se tiene una jerarquía taxonómica con los siguientes animales:


Animal es la clase raíz con los atributos: sonidos, alimentos, hábitat y nombre científico
(todos de tipo String). Esta clase tiene los siguientes métodos abstractos: public abstract
String getNombreCientífico()
public abstract String getSonido()
public abstract String getAlimentos()

26
public abstract String getHábitat()

Los cánidos y los felinos son subclases de Animal.


Los perros son cánidos, su sonido es el ladrido, su alimentación es carnívora, su hábitat
es doméstico y su nombre científico es Canis lupus familiaris.
Los lobos son cánidos, su sonido es el aullido, su alimentación es carnívora, su hábitat
es el bosque y su nombre científico es Canis lupus.
Los leones son felinos, su sonido es el rugido, su alimentación es carnívora, su hábitat es
la pradera y su nombre científico es Panthera leo.
Los gatos son felinos, su sonido es el maullido, su alimentación son los ratones, su
hábitat es doméstico y su nombre científico es Felis silvestris catus.
Además, se requiere en una clase de prueba para desarrollar un método main que genere
un array de animales y la pantalla debe mostrar los valores de sus atributos.

7.17. En una carrera ciclística, un equipo está conformado por un conjunto de ciclistas y se
identifica por el nombre del equipo (tipo String), la suma de los tiempos de carrera de sus
ciclistas en minutos (atributo estático) y país del equipo. Sus atributos deben ser privados.

Un ciclista es una clase abstracta que se describe con varios atributos: identificador (de tipo
int), nombre del ciclista y tiempo acumulado de carrera (en minutos, con valor inicial cero).
Los atributos deben ser privados. Un ciclista tiene un método abstracto imprimirTipo que
devuelve un String.

Los ciclistas se clasifican de acuerdo con su especialidad (sus atributos deben ser privados
y sus métodos protegidos). Estas especialidades no son clases abstractas y heredan los
siguientes aspectos de la clase Ciclista:
Velocista: tiene nuevos atributos como potencia promedio (en vatios) y
velocidad promedio en sprint (Km/h) (ambos de tipo double).
Escalador: tiene nuevos atributos como aceleración promedio en subida (m/s2)
y grado de rampa soportada (grados) (ambos de tipo float).
Contrarrelojista: tiene un nuevo atributo, velocidad máxima (km/h).

Definir clases y métodos para el ciclista y sus clases hijas para realizar las siguientes
acciones:
Constructores para cada clase (deben llamar a los constructores de la clase
padre en las clases donde se requiera).
Métodos get y set para cada atributo de cada clase.
Imprimir los datos de un ciclista. Debe invocar el método de la clase padre e
imprimir los valores de los atributos propios.
Método imprimirTipo que devuelve un String con el texto “Es un xxx”. Donde xxx
es la clase a la que pertenece.

La clase Equipo debe tener los siguientes métodos protegidos:


Métodos get y set para cada atributo de la clase.
Imprimir los datos del equipo en pantalla.
Añadir un ciclista a un equipo.
Calcular el total de tiempos de los ciclistas del equipo (suma de los tiempos de
carrera de sus ciclistas, su atributo estático).
Listar los nombres de todos los ciclistas que conforman el equipo.
Dado un identificador de un ciclista por teclado, es necesario imprimir en
pantalla los datos del ciclista. Si no existe, debe aparecer el mensaje
correspondiente.

27
En una clase de prueba, en un método main se debe crear un equipo y agregar ciclistas de
diferentes tipos.

9. Polimorfismo.
El polimorfismo es una de las características fundamentales de la Programación
Orientada a Objetos y está estrechamente relacionado con la herencia.

Una jerarquía de clases, los métodos y clases abstractas, la sobrescritura de métodos y las
conversiones entre clases de la jerarquía sientan las bases para el polimorfismo. Es
necesario entender bien estos conceptos para comprender el polimorfismo. En esta
entrada se explican y se ven algunos ejemplos de herencia.

El polimorfismo se puede definir como la cualidad que tienen los objetos para responder
de distinto modo a un mismo mensaje.

Para conseguir un comportamiento polimórfico en un programa Java se debe cumplir lo


siguiente:

- Los métodos deben estar declarados (métodos abstractos) y a veces también


pueden estar implementados (métodos no abstractos) en la clase base.
- Los métodos debes estar redefinidos en las clases derivadas.
- Los objetos deben ser manipulados utilizando referencias a la clase base.

Ejemplo 1
¿Cuál es el resultado de la ejecución del siguiente programa?
Clase: Profesor
public class Profesor {
/**
* Método que imprime en pantalla un texto específico identificando *
que el objeto es un Profesor
*/
protected void imprimir() {
[Link](“Es un profesor.”);

}}

Clase: ProfesorTitular
public class ProfesorTitular extends Profesor {
/**
* Método que sobreescribe el método imprimir heredado de la clase *
padre Profesor
*/
protected void imprimir() {
[Link](“Es un profesor titular.”);
}
}

Clase: Prueba

public class Prueba {

28
/**
* Método main que crea un Profesor pero instanciando la clase *
ProfesorTitular. ¿Qué se imprimirá en pantalla?
*/
public static void main(String[] args) {
Profesor profesor1 = new ProfesorTitular();
[Link]();
}
}

¿Cuál es el resultado de la ejecución del siguiente programa basado en el ejercicio


anterior?
public class Prueba {
public static void main(String[] args) {
Profesor profesor1 = new ProfesorTitular();
Profesor profesor2 = (Profesor) profesor1;
[Link]();
}}

Ejemplo 2

Se tienen la siguiente clase abstracta Polígono:

//Clase abstracta Poligono


public abstract class Poligono {
private int numLados;

public Poligono() {
}

public Poligono(int numLados) {


[Link] = numLados;
}

public int getNumLados() {


return numLados;
}

public void setNumLados(int numLados) {


[Link] = numLados;
}

//Sobreescritura del método toString() heredado de Object


@Override
public String toString(){
return "Numero de lados: " + numLados;
}

//Declaración del método abstracto area()


public abstract double area();

Esta clase tiene un atributo entero numLados. Además contiene el método abstracto area()
y se ha modificado (Override) el método toString() heredado de Object.

29
A partir de la clase Poligono vamos a crear las clases Rectangulo y Triangulo como
derivadas de ella.

//Clase Rectangulo hereda de Poligono


public class Rectangulo extends Poligono{
private double lado1;
private double lado2;

public Rectangulo() {
}

public Rectangulo(double lado1, double lado2) {


super(2);
this.lado1 = lado1;
this.lado2 = lado2;
}

public double getLado1() {


return lado1;
}

public void setLado1(double lado1) {


this.lado1 = lado1;
}

public double getLado2() {


return lado2;
}

public void setLado2(double lado2) {


this.lado2 = lado2;
}

// Sobreescritura del método toString() heredado de Poligono


@Override
public String toString() {
return "Rectangulo " + [Link]() +
"\nlado 1 = " + lado1 + ", lado 2 = " + lado2;
}

//Implementación del método abstracto area() heredado de Poligono


@Override
public double area(){
return lado1 * lado2;
}
}

//Clase Triangulo hereda de Poligono


public class Triangulo extends Poligono{
private double lado1;
private double lado2;
private double lado3;
public Triangulo() {
}
public Triangulo(double lado1, double lado2, double lado3) {
super(3);
this.lado1 = lado1;
this.lado2 = lado2;
this.lado3 = lado3;
}

30
public double getLado1() {
return lado1;
}

public void setLado1(double lado1) {


this.lado1 = lado1;
}

public double getLado2() {


return lado2;
}

public void setLado2(double lado2) {


this.lado2 = lado2;
}

public double getLado3() {


return lado3;
}

public void setLado3(double lado3) {


this.lado3 = lado3;
}

// Sobreescritura del método toString() heredado de Poligono


@Override
public String toString() {
return "Triangulo " + [Link]() +
"\nlado 1 = " + lado1 + ", lado 2 = " + lado2 + ",
lado 3 = " + lado3;
}

//Implementación del método abstracto area() heredado de Poligono


@Override
public double area(){
double p = (lado1+lado2+lado3)/2;
return [Link](p * (p-lado1) * (p-lado2) * (p-lado3));
}
}

Vamos a escribir un programa para utilizar estas clases y ver como funciona el
polimorfismo. Vamos a crear objetos de tipo Triángulo y Rectángulo y los guardaremos
en un ArrayList. En lugar de tener dos arrays distintos uno para triángulos y otro para
rectángulos, los guardaremos todos juntos utilizando un ArrayList de Poligonos.

El programa creará objetos, leerá sus datos por teclado y los guardará en el ArrayList de
Polígonos. A continuación, se recorrerá el array y se mostrarán los datos de cada objeto
y su área.

//Clase Principal
public class Polimorfismo1 {

static Scanner sc = new Scanner([Link]);


// ArrayList de referencias a objetos de la clase base Poligono
static ArrayList<Poligono> poligonos = new ArrayList();

31
public static void main(String[] args) {
leerPoligonos();
mostrarPoligonos();
}

//Se pide por teclado el tipo de Poligono a leer y se ejecuta el


método
//leer correspondiente
public static void leerPoligonos() {
int tipo;
do {
do {
[Link]("Tipo de poligono 1-> Rectangulo 2->
Triangulo 0-> FIN >>> ");
tipo = [Link]();
} while (tipo < 0 || tipo > 2);
if (tipo != 0) {
switch (tipo) {
case 1:
leerRectangulo();
break;
case 2:
leerTriangulo();
break;
}
}
} while (tipo != 0);
}

//Se crea un rectángulo y se añade al array


public static void leerRectangulo() {
double l1, l2;
[Link]("Introduzca datos del Rectángulo");
do {
[Link]("Longitud del lado 1: ");
l1 = [Link]();
} while (l1 <= 0);
do {
[Link]("Longitud del lado 2: ");
l2 = [Link]();
} while (l2 <= 0);
Rectangulo r = new Rectangulo(l1, l2);
[Link](r);
//En esta instrucción se produce una conversión implícita o
upcasting
//Se asigna una referencia de una clase derivada (Rectangulo)
//a una referencia de la clase base (Poligono) ya que el
ArrayList es
//de tipo Poligono
}

//Se crea un triángulo y se añade al array


Public static void leerTriangulo() {
double l1, l2, l3;
[Link]("Introduzca datos del Triangulo");
do {
[Link]("Longitud del lado 1: ");
l1 = [Link]();
} while (l1 <= 0);
do {

32
[Link]("Longitud del lado 2: ");
l2 = [Link]();
} while (l2 <= 0);
do {
[Link]("Longitud del lado 3: ");
l3 = [Link]();
} while (l3 <= 0);
Triangulo t = new Triangulo(l1, l2, l3);
[Link](t);
//conversión implícita o upcasting igual que en el método
anterior
}

public static void mostrarPoligonos() {


//Se recorre el ArrayList poligonos que contiene
//referencias a Triangulos y Rectangulos.
//A p de tipo Poligono se le asignarán mediante upcasting
referencias a objetos
//de tipo Triangulo o Rectangulo
for(Poligono p: poligonos){

[Link]([Link]());
[Link](" area: %.2f %n", [Link]());
}
}
}

Después de ejecutar el método leerPoligonos, el ArrayList poligonos contiene mezclados


triángulos y rectángulos. Por ejemplo, podría contener lo siguiente:

triangulo triangulo rectangulo triangulo rectangulo rectangulo triangulo …

Mediante el bucle for

for(Poligono p: poligonos)

se recorre el array y se asigna a la variabale p de tipo Poligono (Clase base) cada elemento
del array. En la instrucción [Link]() mediante p se invoca al método toString(). Pero
¿a qué método toString se ejecutará? Se ejecutará el método toString de las clase derivada
a la que pertenece el objeto referenciado por la variable p (Triangulo o Rectangulo)

Lo mismo ocurre cuando se invoca al método area(). Se ejecutará el método area de la


clase derivada a la que pertenece el objeto referenciado por p.

En este ejemplo se produce el polimorfismo ya que:

- Los métodos toString() y area() están declarados en la clase base. El método


toString está además implementado en la clase base.
- Estos métodos están redefinidos en las clases derivadas.
- Se invocan mediante referencias a la clase base Poligono.

El polimorfismo es posible porque, como ya hemos visto en la entrada correspondiente a


la Herencia, cuando se invoca un método mediante una referencia a una clase base, se

33
ejecuta la versión del método correspondiente a la clase del objeto referenciado y no al
de la clase de la variable que lo referencia.

Por lo tanto, el método que se ejecuta se decide durante la ejecución del programa.

A este proceso de decidir en tiempo de ejecución qué método se ejecuta se le denomina


enlazado dinámico.

El enlazado dinámico es el mecanismo que hace posible el polimorfismo.

El enlazado dinámico es lo opuesto a la habitual vinculación estática o enlazado estático


que consiste en decidir en tiempo de compilación qué método se ejecuta en cada caso.

En el programa anterior podemos ver donde se produce enlazado dinámico y donde


enlazado estático:

public void mostrarPoligonos() {


for(Poligono p: poligonos){
//Para que el polimorfismo se lleve a cabo se está
//aplicando el enlazado dinámico.
//Durante la ejecución se decide qué método se ejecuta.
[Link]([Link]());
[Link](" area: %.2f %n", [Link]());
}
}

public static void main(String[] args) {


// Enlazado estático. Cuando se compila el programa
//ya se sabe que serán esos métodos los que se van a ejecutar.
leerPoligonos();
mostrarPoligonos();
}

10. Interfaces
Una interfaz es una declaración de métodos no estáticos y campos estáticos finales cuyo
fin es definir la estructura y comportamiento de las clases que la implementen de forma
que presenten la misma interfaz pública.

Los elementos de una interfaz son públicos por definición: no es necesario poner la
palabra public, ni se pueden cambiar sus derechos de acceso.

Los atributos siempre son finales, sin necesidad del calificativo final, y hay que darles
un valor inicial.

Dada una interfaz, cualquier clase puede presentar dicha interfaz mediante un
mecanismo denominado

implementación de interfaces. Para ello se escribe:

34
class NombreClase implements Nombrelnterfaz { ... }

Cuando una clase implemente una interfaz, tendrá que sobrecargar sus métodos con
acceso público. Con otro tipo de acceso, el compilador lanzará un error.

Ejemplo:

Como ejemplo se va a utilizar el caso de una aplicación universitaria. En ella serán


docentes, los alumnos y los profesores, pero no los bedeles (ni otros empleados). Los
docentes se distinguen de otras personas en que tendrán un grupo y un horario.

Para ello se va a definir una interfaz de nombre Docente con las operaciones
ponGrupo(), dameGrupo() y dameHorario(). Para los no docentes estas operaciones no
tienen sentido. Sin embargo, sí es cierto que todos los alumnos, profesores, bedeles, etc,
son personas (es decir se pueden crear como derivadas de la clase Persona). De esta
forma se puede escribir:

interface Docente {
void ponGrupo(String grupo. Horario horario);
String dameGrupo();
Horario dameHorario();
}

class Alumno extends Persona implements Docente {


private String grupo;
private Horario horario;
public void ponGrupo(String grupo. Horario horario) {
[Link] = grupo;
[Link] = horario;
}
public String dameGrupo(){
return grupo;
}
public Horario dameHorario(){
return horario;
}
}

abstract class Empleado extends Persona { ... }

class Profesor extends Empleado implements Docente {


String grupo;
boolean esMatutino;
public void ponGrupo(String grupo, Horario horario)
[Link] = grupo;
esMatutino =(horario= = [Link]ÑANA);
}
public String dameGrupo(){
return grupo;
}
public Horario dameHorario()
if (esMatutino){
return MAÑANA;
}else{
return TARDE;

35
}
}
}
class Bedel extends Empleado { ... }

En el ejemplo se ha hecho de forma diferente intencionadamente para demostrar esta


diferencia. Una clase puede implementar varias interfaces, con la siguiente sintaxis:

class ClaseA implements Interfaces. InterfaceC { ... }

La línea anterior declara una clase ClaseA que implementa las interfaces InterfaceB e
InterfaceC.

Si alguno de los métodos queda sin implementar, la clase es abstracta. En ese caso, es
necesario definirlo de forma explícita, añadiendo el calificativo abstract a la clase y
añadiendo la cabecera del método que se deja sin implementar anteponiendo a su vez el
calificativo abstract. De esta forma queda patente que se está definiendo una
implementación parcial, con la intención de que al programador no se le pasen cosas
desapercibidas. Una interfaz puede heredar de tantas interfaces como sea necesario. Lo
que consigue añadir nuevos métodos a los existentes en las interfaces de las que hereda.
Una clase que implemente esta interfaz, tiene que implementar todos los métodos
declarados en ella, además de los heredados de las otras.

interface InterfazNueva extends InterfaceX. InterfaceY { ... }

Ejercicio:

11.18. Realizar cada uno de los apartados:

• Escriba un programa para una biblioteca que contenga libros y revistas.

a) Las características comunes que se almacenan tanto para las revistas como para
los libros son el código, el titulo y el año de publicación. estas tres
características se pasan como parámetros en el momento de crear los objetos.
b) Lis libros tienen además un atributo prestado. Los libros cuando se crean no
están prestados.
c) Las revistas tienen un número. En el momento de crear las revistas se pasa el
número por parámetro.
d) Tanto las revistas como los libros deben tener aparte de los constructores un
método toString() que devuelva el valor de todos los atributos en una cadena de
caracteres. También tienen un método que devuelve el año de publicación y otro
para el código.
e) Para prevenir posibles cambios en el programa se tienen que implementar una
interfaz Prestable con los métodos prestar (), devolver() y prestado(). La clase
libro implementa esa interfaz.
36
• Escriba una aplicación en la que se implementen dos métodos:

a) cuentaPrestados(): recibe por parámetro un array de objetos y devuelve cuantos


de ellos estan prestados.
b) publicacionesAnterioresA(): recibe por parámetro un array de Publicaciones y
un año, devuelve cuántas publicaciones tienen fecha anterior al año recibido por
parámetro.
c) En el método main() crear un array de Publicaciones con 2 libros y 2 revistas,
prestar uno de los libros, mostrar por pantalla los datos almacenados en el array
y mostrar por pantalla cuantas publicaciones hay prestadas y cuántas hay
anteriores a 1980 utilizando los métodos escritos anteriormente.

11. Genéricos

Los métodos genéricos en Java y las clases genéricas permiten a los programadores
especificar, con una única declaración de método, un conjunto de métodos relacionados,
o con una única declaración de clase, un conjunto de tipos relacionados,
respectivamente.

Los genéricos también proporcionan seguridad de tipo en tiempo de compilación que


permite a los programadores detectar tipos no válidos en tiempo de compilación.

Usando el concepto genérico de Java, podríamos escribir un método genérico para


clasificar una matriz de objetos, luego invocar el método genérico con matrices de
enteros, matrices dobles, matrices de cadenas, etc., para ordenar los elementos de la
matriz.

Métodos genéricos

Puede escribir una única declaración de método genérico que se puede llamar con
argumentos de diferentes tipos. En función de los tipos de argumentos pasados al
método genérico, el compilador maneja cada llamada de método de manera apropiada.
Las siguientes son las reglas para definir métodos genéricos:

• Todas las declaraciones de métodos genéricos tienen una sección de parámetros


de tipo delimitada por corchetes angulares (<y>) que preceden al tipo de retorno
del método (<E> en el siguiente ejemplo).
• Cada sección de parámetros de tipo contiene uno o más parámetros de tipo
separados por comas. Un parámetro de tipo, también conocido como variable de
tipo, es un identificador que especifica un nombre de tipo genérico.
• Los parámetros de tipo se pueden usar para declarar el tipo de retorno y actuar
como marcadores de posición para los tipos de argumentos pasados al método
genérico, que se conocen como argumentos de tipo real.

37
• El cuerpo de un método genérico se declara como el de cualquier otro método.
Tenga en cuenta que los parámetros de tipo solo pueden representar tipos de
referencia (Integer, String, etc), no tipos primitivos (como int, double y char).

Ejercicio:

11.19. Realizar los siguientes códigos:

Escriba una clase Matriz genérica con los siguientes métodos:

• constructor que recibe por parámetro el número de filas y columnas de la matriz.


• set() recibe por parámetro la fila, columna y el elemento a insertar. El elemento es de
tipo genérico. Este método inserta el elemento en la posición indicada.
• get() recibe por parámetro la fila y la columna. Devuelve el elemento en esa posición.
El elemento devuelto es del tipo genérico.
• columnas () devuelve el número de columnas de la matriz.
• filas () devuelve el número de filas de la matriz.
• toString() devuelve en forma de String la información de la matriz.

Escriba una aplicación que:

• Cree una matriz de lnteger de 4 filas y 2 columnas.


• Rellénela con números consecutivos comenzando por el número l.
• Muestre por pantalla la matriz.
• Muestre por pantalla el contenido de la celda en la fila O columna l.

38

También podría gustarte