Está en la página 1de 147

Ejercicios Tema 2:

Herencia y Polimorfismo

Fundamentos de Programación II 1
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 1
¿Qué tipos de relación hay entre las siguientes clases?

Personal de la Universidad

Herencia Herencia

1 n
PAS Profesor Estudiante

Asociación

a) herencia y asociación
b) herencia y dependencia
c) dependencia y asociación
d) transposición y bifuncionalismo

Fundamentos de Programación II 2
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 2 (I)
class Programa {
public static void main(String [ ] args){
Clase1 obj1=new Clase1();
obj1.imprimir(4);
Clase2 obj2=new Clase2();
obj2.imprimir(3);
14 8 7 1
}
}

class Clase1 {
protected int prop1=10,prop2=4; Se hereda el valor
public void imprimir(int i){ inicial de prop1 y
prop1=prop1+i;
prop2=prop2+i; prop2, pero no su
System.out.print(prop1+" "+prop2+" "); valor tras haber sido
} modificado en el
} objeto obj1 de la
class Clase2 extends Clase1 {
public void imprimir(int i){ Clase1.
prop1=prop1-i;
prop2=prop2-i;
System.out.print(prop1+" "+prop2); Nota:
}
} El método imprimir está
sobrescrito en la Clase 2
Fundamentos de Programación II 3
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 2 (II)
¿Y si prop 1 y prop 2 se definen como static?
class Programa {
public static void main(String [ ] args){
Clase1 obj1=new Clase1();
obj1.imprimir(4); 14 8
Clase2 obj2=new Clase2(); prop1 y prop2 se heredan
obj2.imprimir(3);
} 11 5 igual que en el caso
} anterior. Sin embargo al
ser estáticas las
class Clase1 { comparten todos los
static protected int prop1=10,prop2=4;
public void imprimir(int i){ objetos. Por tanto, cuando
prop1=prop1+i; se modifican a través de
prop2=prop2+i; obj1 valen lo mismo que en
System.out.print(prop1+" "+prop2+" "); el caso anterior, pero no
}
} cuando se modifican
class Clase2 extends Clase1 { posteriormente con obj2.
public void imprimir(int i){ Al ser estáticas las
prop1=prop1-i; variables son las mismas
prop2=prop2-i;
System.out.print(prop1+" "+prop2); en las dos clases (se
} comparten)
}
Fundamentos de Programación II 4
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 2 (III)
¿y si en lugar de ser prop1 y prop2 protected son private?
class Programa {
public static void main(String [ ] args){
Clase1 obj1=new Clase1();
obj1.imprimir(4);
Clase2 obj2=new Clase2();
obj2.imprimir(3);
}
}

class Clase1 { Se produce un error


private int prop1=10,prop2=4;
public void imprimir(int i){ porque prop1 y
prop1=prop1+i; prop2 no las puede
prop2=prop2+i; heredar Clase 2
System.out.print(prop1+" "+prop2+" ");
}
}
class Clase2 extends Clase1 {
public void imprimir(int i){
prop1=prop1-i;
prop2=prop2-i;
System.out.print(prop1+" "+prop2);
}
}
Fundamentos de Programación II 5
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 3
¿Qué modificador de visibilidad debo usar en los siguientes casos?

Para un atributo de una clase que va a tener hijas protected


Para un método de soporte private

Para un método de servicio public

Para un atributo de una clase que no va a tener hijas private

Fundamentos de Programación II 6
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 4
abstract class Uno { Clase abstracta que NO implementa frase.
protected int i=2;
abstract public void frase();

}
class Dos extends Uno { i localDos
Clase prevalece
hereda sobre
de la edeimplementa
Uno ejemplar frase.
public void frase() { heredada de class Uno. i=3
int i=3;
System.out.println("Estoy en un objeto de clase Dos con i:“ + i);
}
}
class Tres extends Dos { Clase Tres hereda de Dos y sobrescribe frase
public void frase() { i de ejemplar heredada de class Uno. i=2
System.out.println("Estoy en un objeto de clase Tres con i:"+i);
}
}
class Driver {
public static void main(String[] args) {
Uno [] lista =new Uno [2];
lista [0]= new Dos(); lista: referencia polimórfica
lista [1]= new Tres();
for (int i=0; i<2; i++){
lista[i].frase();
} Estoy en un objeto de clase Dos con i:3
} Estoy en un objeto de clase Tres con i:2
}
Fundamentos de Programación II 7
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (I)
En una tienda se venden 2 tipos de ordenadores: portátiles y de sobremesa.

- Ambos tipos de ordenadores se caracterizan por su código y por su


precio.

- Cada tipo de ordenador tiene un eslogan:


- portátil: "Ideal para sus viajes"
- sobremesa: "Es el que más pesa, pero el que menos cuesta"

- Otros atributos:
- portátil: atributo peso
- sobremesa: atributo descripción del tipo de torre

 Realice un diseño indicando las clases que hay que tener en cuenta
(incluyendo atributos y métodos) y su relación.

 Implemente en Java dichas clases.

Fundamentos de Programación II 8
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (II)
O rde nador

Portatil Sobre me sa

O rdenador {abstract}

#pre cio:double
#codigo:int

+O rde nador(pre cio:double , codigo:int)


+slogan(): String {abstract}
+de v ue lv e pre cio():double
+de v ue lv e codigo():int

Fundamentos de Programación II 9
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (III)

Portatil

-pe so:double

+Portatil(pre cio:double , codigo:int, pe so:double )


+slogan(): String
+de v ue lv e pe so():double
+toString():String

Sobre me sa

-tipotorre :String

+Sobre me sa(pre cio:double , codigo:int, tipotorre :String)


+slogan(): String
+de v ue lv e torre ():String
+toString():String

Fundamentos de Programación II 10
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (IV)
abstract class Ordenador {
protected double precio;
protected int codigo;

public Ordenador (double precio, int codigo){


this.precio=precio;
this.codigo=codigo;
}

abstract public String slogan ();

public double devuelveprecio(){


return precio;
}

public int devuelvecodigo(){


return codigo;
}

}//fin clase Ordenador

Fundamentos de Programación II 11
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (V)
class Portatil extends Ordenador {
private double peso;

public Portatil(double precio, int codigo, double peso) {


super (precio,codigo);
this.peso=peso;
}

public double devuelvepeso(){


return peso;
}

public String slogan(){


return "Ideal para sus viajes";
}

public String toString(){


return "Los datos del portatil son:\ncodigo: "+codigo+
" peso: " + peso + " precio: "+precio;
}
}//clase Portatil

Fundamentos de Programación II 12
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (VI)
class Sobremesa extends Ordenador {
private String tipotorre;

public Sobremesa (double precio, int codigo,


String tipotorre) {
super (precio,codigo);
this.tipotorre=tipotorre;
}

public String devuelvetipotorre(){


return tipotorre;
}

public String slogan(){


return "Es el que mas pesa, pero el que menos cuesta";
}

public String toString(){


return "Los datos del sobremesa son:\ncodigo: "+codigo+
" tipotorre: " + tipotorre + " precio: "+precio;
}
}//fin clase Sobremesa
Fundamentos de Programación II 13
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (VII)
class Principal {
public static void main (String [] args){
Ordenador [] orde=new Ordenador [2];
orde[0]=new Portatil (1100,1,2.3);
orde[1]=new Sobremesa (700,2,"grande");

for (int i=0; i<2; i++){


System.out.println(orde[i].toString());
System.out.println(orde[i].slogan()+"\n"); }
}
}//fin clase Principal

Fundamentos de Programación II 14
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 5 (VIII)
En el main: System.out.println(orde[i].toString());

Sin el método toString definido en la clase Ordenador:

public String toString(){


return "Los datos del portatil son: " + "codigo: "+ codigo + ";
precio: " + precio + " euros" + "; peso: " + peso + " kg";
}
public String toString(){
return "Los datos del sobremesa son: " + "codigo: " + codigo + ";
precio: " + precio + " euros" + "; tipotorre: " + tipotorre;
}

Con el método toString definido en la clase Ordenador:

public String toString() {


return "codigo: " + codigo + "; precio: " + precio + " euros";
}

public String toString(){


return "Los datos del portatil son: " + super.toString() +
"; peso: " + peso + " kg";
}
public String toString(){
return "Los datos del sobremesa son: " + super.toString() +
"; tipotorre: " + tipotorre;
}
Fundamentos de Programación II 15
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (I)
- En un banco tenemos varios tipos de cuentas bancarias
- En todas es posible retirar fondos y hacer depósitos.
- Tres tipos de cuentas: cuenta corriente, libreta de ahorro y libreta 2000
- Las cuentas corrientes se usan para realizar pagos y no proporcionan ningún
interés. La cuenta corriente puede tener asociada una libreta de ahorro para cubrir
descubiertos de la cuenta corriente.
- Las libretas de ahorro proporcionan un interés del 4%.
- La libreta 2000 es un tipo de libreta de ahorro que rinde un mayor interés (del 8%)
pero la retirada de fondos está penalizada con un 2% de la cantidad retirada.

- En estas condiciones:
a) Construir un diagrama de clases usando UML, incluyendo los atributos y métodos
en cada clase. Incluya también las relaciones entre las distintas clases
b) Programar las clases resultantes
c) Construir un programa ejemplo que use las clases del apartado a). En el programa
deben crearse objetos de cada una de las clases, inicializando las cuentas con unos
valores iniciales. Además se retiraran fondos de cada uno de los tipos de cuenta, se
actualizarán los intereses de la libreta 2000 y se depositará una determinada
cantidad en la libreta 2000.

Fundamentos de Programación II 16
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (II)
Este programa es un claro ejemplo de jerarquía de clases

Cuenta_bancaria

Herencia

Cuenta_corriente 1 1 Libreta_de_ahorro

Asociación
Herencia

Libreta_2000

Fundamentos de Programación II 17
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (III)
C u e n ta _ ba n ca ria

# num e ro :int
# s aldo :do uble

+ C ue nta_ banc aria (num e ro :int,s aldo _ inic ial:do uble )


+ de po s itar (c antidad:do uble ):v o id
+ re tirar (c antidad:do uble ):int
+ c o ns ultar_ s aldo ( ):do uble
+ c o ns ultar_ num e ro ():int

L ibre ta _ de _ a h o rro e x te n ds C u e n ta _ ba n ca ria

# inte re s :do uble

+ L ibre ta_ de _ aho rro (num e ro :int,s aldo _ inic ial:do uble ,inte re s :do uble )
+ c alc ular_ inte re s e s ():v o id
+ c o ns ultar_ inte re s e s ():do uble

Fundamentos de Programación II 18
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (IV)
L ibre ta _ 2 0 0 0 e x te n ds L ibre ta _ de _ a h o rro

-pe nalizac io n:do uble

+ L ib re ta_ 2 0 0 0 (n um e ro :int,s aldo _ inic ial:do uble , inte re s :d o uble , pe nalizac io n:do uble )
+ re tirar(c antidad:do uble ):int
+ c o ns ultar_ pe nalizac io n():do uble

C u e n ta _ co rrie n te e x te n ds C u e n ta _ ba n ca ria

-c ue nta_ as o c iada:L ibre ta_ de _ aho rro

+ C ue nta_ c o rrie nte (num e ro :int,s aldo _ inic ial:do uble , libre ta:L ibre ta_ de _ aho rro )
+ re tirar (c antidad:do uble ):int
+ c o ns ultar_ c ue nta_ as o c iada ( ):L ibre ta_ de _ aho rro

Fundamentos de Programación II 19
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (V)
Comentarios:
- Los métodos y atributos que incorporemos en las clases dependen de los
requisitos que nos exijan, aunque es mejor planificar para el cambio:
- Por ejemplo, si nos indicaran que las cuentas se abren con saldo inicial de
cero y que después se hacen los ingresos, no tendríamos que usar una
variable saldo_inicial en los constructores. Sin embargo, poniéndola cubrimos
un futuro cambio consistente en abrir una cuenta con un saldo inicial. Para el
caso actual bastaría con introducir valor cero para la variable saldo_inicial.
- Por la misma razón, se introducen los intereses y la penalización a través del
constructor.

- Obsérvese cómo el método retirar se sobrescribe en varias clases. En la clase


Libreta_2000 debe incluir la penalización por retirada y en la clase Cuenta_Corriente
la retirada de fondos de la cuenta asociada

- El método retirar devuelve un entero para que pueda saberse si hay saldo o no en la
cuenta en el método main e imprimir la información necesaria

- Otra posible solución sería declarar la clase Cuenta_bancaria como abstracta, el


método retirar sería abstracto y todas las clases lo sobrescribirían. Sería llevarse el
código de retirar de Cuenta_bancaria a Libreta_de_ahorro. Siempre que sólo
existieran estos tres tipos de cuenta daría igual cualquiera de las dos
aproximaciones. Si hay más tipos de cuenta que usan el mismo código retirar que
hay en Cuenta_bancaria sería mejor dejarlo tal y como está para no estar repitiendo
el código retirar en cada tipo de cuenta.
Fundamentos de Programación II 20
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (VI)
class Cuenta_bancaria {
protected int numero;
protected double saldo;
public Cuenta_bancaria(int numero, double saldo_inicial) {
this.numero=numero;
saldo=saldo_inicial;
}
public void depositar(double cantidad) {
saldo+=cantidad;
}
public int retirar(double cantidad) {
int control=1;
if (saldo < cantidad)
control=0;
else {
saldo-=cantidad;
}
return control;
}
public double consultar_saldo() {
return saldo;
}
public int consultar_numero() {
return numero;
}
} // Fin Cuenta_bancaria
Fundamentos de Programación II 21
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (VII)
class Libreta_de_ahorro extends Cuenta_bancaria {

protected double interes;

public Libreta_de_ahorro(int numero, double saldo_inicial,


double interes) {
super(numero, saldo_inicial);
this.interes=interes;
}

public void calcular_intereses() {


saldo+=saldo*interes/100.0; //saldo=saldo+saldo*interes/100.0
}

public double consultar_intereses() {


return interes;
}
} // Fin Libreta_de_ahorro

Fundamentos de Programación II 22
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (VIII)
class Libreta_2000 extends Libreta_de_ahorro {
private double penalizacion; // Penalizacion por retirada

public Libreta_2000(int numero, double saldo_inicial,


double interes, double penalizacion) {

super(numero, saldo_inicial, interes);


this.penalizacion=penalizacion;
}

public int retirar(double cantidad) {


int control=1;
double total = cantidad*(1.0+penalizacion/100.0);
if (saldo < total)
control=0;
else {
saldo-= total;
}
return control;
}
public double consultar_penalizacion() {
return penalizacion;
}
} // Fin Libreta_2000

Fundamentos de Programación II 23
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (IX)
class Cuenta_corriente extends Cuenta_bancaria {
private Libreta_de_ahorro cuenta_asociada;
public Cuenta_corriente(int numero, double saldo_inicial,
Libreta_de_ahorro libreta) {
super(numero, saldo_inicial);
cuenta_asociada=libreta;
}
public Libreta_de_ahorro consultar_cuenta_asociada(){
return cuenta_asociada;
}
public int retirar(double cantidad) {
int control=1;
if (saldo < cantidad){
if (cuenta_asociada.consultar_saldo() < (cantidad-saldo) )
control=0;
else {
cuenta_asociada.retirar(cantidad-saldo);
saldo=0.0;
control=2;
}
}
else {
saldo-=cantidad;
}
return control;
}
} // Fin Cuenta_corriente
Fundamentos de Programación II 24
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (X)
class Herencia {
public static void main(String [] args) {
int control=0;
Libreta_de_ahorro libreta =
new Libreta_de_ahorro(12345, 2000, 4);
Libreta_2000 libreton = new Libreta_2000(23456, 2000, 8, 2);
Cuenta_corriente cuenta =
new Cuenta_corriente(34567, 2000, libreta);

control=libreta.retirar(100);
System.out.println("Ha solicitado retirar 100 euros de su
libreta");
if (control==0) {
System.out.println("No hay fondos suficientes en su libreta");
}
else {
System.out.println("Saldo en su libreta despues de la retirada:
"+libreta.consultar_saldo());
}

System.out.println();

Fundamentos de Programación II 25
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (XI)
control=cuenta.retirar(3000);
System.out.println("Ha solicitado retirar 3000 euros de su cuenta");

if (control==0) {
System.out.println("No hay fondos suficientes");
}

else {
if (control==1) {
System.out.println("Saldo despues de la retirada: "+
cuenta.consultar_saldo());
}
else {
System.out.println("No tiene saldo en la cuenta.\n
Retirando fondos de la cuenta asociada...");
System.out.println("Saldo en su cuenta después de la
retirada: "+ cuenta.consultar_saldo());
System.out.println("Saldo en su libreta asociada después de la
retirada: "+ libreta.consultar_saldo());
}
}
System.out.println();

Fundamentos de Programación II 26
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (XII)
System.out.println("Ha solicitado retirar 200 euros de su Libreta
2000");
System.out.println("Recuerde que la retirada le supone una
penalizacion del 2%");

control=libreton.retirar(200);

if (control==0) {
System.out.println("No hay fondos suficientes");
}
else {
System.out.println("Saldo despues de la retirada de su Libreta
2000: "+libreton.consultar_saldo());
}
System.out.println();

Fundamentos de Programación II 27
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (XIII)
libreton.calcular_intereses();

System.out.println("Actualizando intereses....");
System.out.println("Saldo después de actualizar intereses: "+
libreton.consultar_saldo());
System.out.println();

libreton.depositar(100);

System.out.println("Ha solicitado depositar 100 euros de su


Libreta 2000");
System.out.println("Saldo después del depósito de 100 euros en su
Libreta 2000: "+
libreton.consultar_saldo());

}//fin main
} //fin clase

Fundamentos de Programación II 28
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 6 (XIV)
Ha solicitado retirar 100 euros de su libreta
Saldo en su libreta despues de la retirada: 1900.0

Ha solicitado retirar 3000 euros de su cuenta


No tiene saldo en la cuenta.
Retirando fondos de la cuenta asociada...
Saldo en su cuenta después de la retirada: 0.0
Saldo en su libreta asociada después de la retirada: 900.0

Ha solicitado retirar 200 euros de su Libreta 2000


Recuerde que la retirada le supone una penalizacion del 2%
Saldo despues de la retirada de su Libreta 2000: 1796.0

Actualizando intereses....
Saldo después de actualizar intereses: 1939.68

Ha solicitado depositar 100 euros de su Libreta 2000


Saldo después del depósito de 100 euros en su Libreta 2000: 2039.68

Fundamentos de Programación II 29
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 7
class Padre {
protected int aa=0;
public int aa() {
return aa;
}
}
class Hija extends Padre {
public Hija (int bb) {
this.aa=bb+1; //this no haría falta
}
}
class Nieta extends Hija {
public Nieta (int cc) {
super(cc+2);
}
}
class Familia {
public static void main(String [] args){
Hija h= new Hija(4); h= new Hija (4)  bb=4  aa=bb+1=5
h=f(h);
System.out.println (h.aa()); 8
}
private static Nieta f (Padre h) {
Nieta n=new Nieta (h.aa());
N=new Nieta (5)  cc=5 
return n;
} super(5+2) bb=7 this.aa=7+1=8
}
Fundamentos de Programación II 30
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 8

Publicación

Tesis Revista

clase publicación tiene los métodos: devuelve_autor y devuelve_editorial.


clase tesis tiene además el método devuelve_departamento
clase revista devuelve_número_de_revista.

¿Qué métodos podrían ser invocados usando una variable polimórfica de tipo publicación?

a)devuelve_autor, devuelve_editorial y devuelve_número_de revista


b)devuelve_numero_de_revista y devuelve_departamento
c)devuelve_autor, devuelve_editorial, devuelve_departamento y devuelve_número_de_revista
d)devuelve_autor, devuelve_editorial

Son los métodos de la clase Publicación

Fundamentos de Programación II 31
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 9
¿Cuál de las siguientes afirmaciones es la única correcta?

a) Para que una clase sea abstract debe tener al menos un método
abstract
b) Se pueden crear objetos de una clase abstract
c) Se pueden crear referencias de una clase abstract
d) Un atributo private en una clase abstract puede ser heredado por una
subclase y modificado en esa subclase

Fundamentos de Programación II 32
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 10
Naturaleza Naturaleza n;
Animal a;
Herbívoro h;
Elefante e;
Rinoceronte r;
Animal

Hervíboro

Elefante Rinoceronte

a=n Incorrecta. No puede haber asignación directa sin un molde: a= (Animal) n;


Incorrecta: entre Rinoceronte y Elefante no hay relación de herencia
e=r Correcta
h=e Correcta
a=h

Fundamentos de Programación II 33
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 11
Cuerda c;
In stru m en to Viento v;
{ a bs tra cta } Arpa a;
Instrumento i;

V ie n to C u e rda

A rpa

a=v Incorrecta. Entre Arpa y Viento no hay relación de herencia


Incorrecta: Entre Viento y Cuerda no hay relación de herencia
v=c Incorrecta. No puede haber asignación directa sin un molde: c= (Cuerda)i
c=i Correcta. Instrumento es clase padre de Cuerda que a su vez es padre de Arpa
i=a

Fundamentos de Programación II 34
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 12 (I)
- Implemente el código de una interfaz llamada Primera que contenga dos
métodos A y B.

//Primera interfaz
interface Primera{
void A();
void B();
}

- ¿Por qué los métodos devuelven void()? Porque en el enunciado nos


dicen que la implementación de los métodos es una sentencia para
imprimir por lo que no devuelven nada

- Defina otra interfaz llamada Segunda que herede de la anterior y además


contenga un método llamado C.

//Segunda interfaz
interface Segunda extends Primera{
void C();
}

Fundamentos de Programación II 35
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 12 (II)
- Escriba el código de otra clase llamada Objetos que use la segunda
interfaz. ¿Cuántos métodos debe implementar esta clase? Implemente
dichos métodos de forma que cada método imprima una línea indicando el
nombre del método.

La clase debe implementar 3 métodos, los dos de la interfaz Primera y el de


la interfaz Segunda.
Si la clase Objetos no implementara alguno de los métodos ésta debería ser
declarada abstracta.

class Objetos implements Segunda {


public void A(){
System.out.println("Método A");
}
public void B(){
System.out.println("Método B");
}
public void C(){
System.out.println("Método C");
}
}//Fin clase Objetos

Fundamentos de Programación II 36
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 12 (III)
- Cree un programa que utilice los métodos definidos.

class Ejercicio {
public static void main(String [ ] args){
Objetos objeto1= new Objetos();
objeto1.A();
objeto1.B();
objeto1.C();
}
}//Fin clase Ejercicio

El programa imprimirá:

Método A
Método B
Método C

Fundamentos de Programación II 37
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 13 (I)
Construya un programa que calcule el volumen molar de una sustancia a una presión y
temperatura dadas usando la ecuación de estado de un gas ideal:
pV=nNakT
donde p es la presión, V el volumen, n el número de moles, N a la constante de
Avogadro, k la constante de Boltzmann y T la temperatura.

Na (contante de Avogadro)= 6.023 1023 partículas/mol


k (constante de Boltzmann)= 1.38066 10-23 J/K

El programa debe hacer uso de dichas constantes definiéndolas a través de una


interfaz.
Lógicamente, si creamos la interfaz es porque las constantes recogidas tienen
interés para varias clases (cada una de ellas implementará la interfaz).

Vamos a realizar la lectura con la clase Scanner y la impresión con printf

Fundamentos de Programación II 38
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 13 (II)
import java.util.Scanner;
import java.util.Locale;

interface Constantes_fisicas {
double Na=6.023e23; // Cte de Avogadro en (partículas/mol)
double k=1.38066e-23; // Constante de Boltzmann en J/K
}

Fundamentos de Programación II 39
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 13 (III)
class Herencia implements Constantes_fisicas {
public static void main(String[] args) {
Scanner leer=new Scanner (System.in);
leer.useLocale(Locale.US);
double p, T, v;
System.out.println("Introduzca la presion en atmósferas y
la temperatura en grados Kelvin");
System.out.print ("p(atm)= ");
p=leer.nextDouble(); // 1Pa= 1 Newton/(m*m); 1atm = 101325 Pa

System.out.print ("T(K)= ");

T=leer.nextDouble();
p=p*101325; //Conversión de atm a Pascales

v=k*Na*T/p; // Volumen molar (metros cúbicos)


v=v*1000.0; // litros (1 metro cubico = 1000 litros)
System.out.printf(Locale.US,
"Volumen molar= %.2f litros", v);
}//fin main
}//Herencia
Fundamentos de Programación II 40
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 13 (IV)
Entrada:
p= 1 atm. (101325 Pa)
T= 298.15 K (25 ºC)

Salida:
Volumen molar= 24.47 litros

Fundamentos de Programación II 41
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 14 (I)
class Ejercicio {
public static void main (String [] args) {
Vehiculo v= new Vehiculo("AAA", 1000);
Coche c = new Coche("BBB", 1000);

v.incrementar_precio(100);
System.out.print(v.devolver_marca()+” “);
System.out.println(v.devolver_precio());

c.incrementar_precio(100);
System.out.print(c.devolver_marca()+” “);
System.out.println(c.devolver_precio());

v=c;

v.incrementar_precio(100);
System.out.print(v.devolver_marca()+” “);
System.out.println(v.devolver_precio());
}
}

Fundamentos de Programación II 42
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 14 (II)
class Vehiculo {
protected String marca;
protected double precio;
public Vehiculo (String marca, double precio) {
this.marca=marca;
this.precio=precio;
}
public void incrementar_precio(double p) {
precio=precio+p;
}
public double devolver_precio(){
return precio;
}
public String devolver_marca(){
return marca;
}
}
class Coche extends Vehiculo {
public Coche (String marca, double precio){
super (marca,precio);
}
public void incrementar_precio(double p) {
precio=precio+2*p;
}
}
Fundamentos de Programación II 43
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 14 (III)
class Ejercicio {
public static void main (String [] args) {
Vehiculo v= new Vehiculo("AAA", 1000);
Coche c = new Coche("BBB", 1000);

v.incrementar_precio(100);
System.out.print(v.devolver_marca()+” “);
System.out.println(v.devolver_precio()); AAA 1100.0

c.incrementar_precio(100);
System.out.print(c.devolver_marca()+” “);
System.out.println(c.devolver_precio()); BBB 1200.0

v=c;

v.incrementar_precio(100);
System.out.print(v.devolver_marca()+” “);
System.out.println(v.devolver_precio()); BBB 1400.0
}
}

Fundamentos de Programación II 44
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 15 (I)
¿Cuál es el error del siguiente programa?

interface A {
double a=2.3;
void imprimeresultadoA () {
System.out.println ("valor de a"+ a);
}
}

interface B {
int b=435;
void imprimeresultadoB () ;
}

class AA implements A, B {
double aa=324.32;
public void imprimeresultadoA () {
System.out.println ("valor de a "+ a+ “ valor de aa "+ aa);
}
public void imprimeresultadoB () {
System.out.println ("valor de b "+ b+ “ valor de aa "+ aa);
}
}
Fundamentos de Programación II 45
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 15 (II)
class Principal {
public static void main (String [] args) {
AA ob1=new AA();
ob1.imprimeresultadoA();
ob1.imprimeresultadoB();
}
}

NO se pueden implementar métodos en una interfaz.

La interfaz A implementa un método. Para que el programa fuera correcto la interfaz A


debería ser:

interface A {
double a=2.3;
void imprimeresultadoA ();
}

Fundamentos de Programación II 46
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (I)
Una tienda de informática vende dos tipos de artículos (software y hardware) ambos
caracterizados por su código (de tipo char) y su descripción.
En los productos software hay que indicar el tipo de producto (con una cadena)
En los hardware se debe indicar si es un periférico o no.

Para saber el precio de un artículo utilice una interface que indique que para un
artículo cuyo código es A el precio es 100.0 euros, si el código es B el precio es 50.3;
para un artículo con código C el precio es 150.50 euros.

Los productos hardware sólo serán A ó B y si es un periférico el precio se


incrementará en un 10%.
Los productos software serán B ó C incrementándose el precio del artículo en un 5% si
el software es de tipo ProgramaJuegos.

- La interface debe tener un método abstracto.

a) Dibuje en UML los diagramas de las clases y las relaciones entre ellas. Para cada
clase debe indicar los atributos y métodos teniendo en cuenta que se puede consultar
y modificar cada atributo.
b) Implemente las clases y la interfaz.
c) Realice un programa principal donde cree un objeto software y otro hardware y
muestre el precio y demás características del objeto.

Fundamentos de Programación II 47
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (II)
a) Relación entre clases

Primera opción

La clase Producto implementa la interfaz, por tanto, las constantes y el método


abstracto (calcularPrecio) de la interfaz estarán en la clase Producto y los pueden
heredar
las clases Software y Hardware.
Como en la clase Producto no tiene sentido codificar dicho método, la clase Producto
tendrá un método abstracto (proveniente de la interfaz) y, por tanto, la clase Producto
será abstracta. En las clases Software y Hardware se codificará el método.

P ro d u cto < < in te rfa ce > >


{ a bs tra ct} Pre cio s

H a rdwa re S o ftwa re

Fundamentos de Programación II 48
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (III)
a) Relación entre clases

Segunda opción

En este caso son directamente las clases Hardware y Software las que implementan la
interfaz, por tanto, la clase Producto no tendrá las constantes ni el método de la
interfaz y no debe ser abstracta.
Desventaja: Al no estar definido el método de la interfaz en la clase Producto no se
puede usar polimorfismo para acceder a ese método.

Pro du cto

H a rdwa re S o ftwa re

< < in te rfa ce > >


Pre cio s

Fundamentos de Programación II 49
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (IV)
Escogemos la primera opción

Diagrama UML para cada clase y la interfaz

<<interface>>
Precios
+A:double=100.0
+B:double=50.3
+C:double=150.5
+calcularPrecio():double

Producto {abstract}
#codigo:char
#descripcion:String
+ Producto(codigo:char,descripcion:String)
+ getCodigo():char
+ cambiarCodigo(nuevoCodigo:char):void
+ getDescripcion():String
+ cambiarDescripcion(nuevaDescripcion:String):void

Fundamentos de Programación II 50
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (V)
El método calcularPrecio() lo implementan Hardware y Software por eso aparece en el
diagrama UML de ambas clases

Hardware

-periferico:boolean
Hardware(codigo:char,descripcion:String,perifierico:boolean)
+ getPeriferico():boolean
+cambiarPeriferico(nuevoPeriferico:boolean):void
+calcularPrecio():double

Software
- tipo:String
Software(codigo:char,descripcion:String,tipo:Strin
g)
+ getTipo():String
+cambiarTipo(nuevoTipo:String):void
+calcularPrecio():double

Fundamentos de Programación II 51
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (VI)
b) Implementación de las clases y la interfaz

interface Precios{
double A=100.0;
double B=50.3;
double C=150.5;
double calcularPrecio();
}//fin interface

Recordatorio:
En una interfaz todas las “variables” son constantes (final) y públicas(public) por lo
que no hay que especificarlo en la interfaz.
Todos los métodos son públicos y abstractos por lo que tampoco se especifica.

Fundamentos de Programación II 52
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (VII)
abstract class Producto implements Precios{
protected char codigo;
protected String descripcion;
public Producto (char codigo, String descripcion){
this.codigo=codigo;
this.descripcion=descripcion;
}
public void cambiarCodigo(char nuevoCodigo){
codigo=nuevoCodigo;
}
public void cambiarDescripcion(String nuevaDescripcion){
descripcion=nuevaDescripcion;
}
public char getCodigo( ){
return codigo;
}
public String getDescripcion( ){
return descripcion;
}
}//fin Producto

La clase Producto es abstracta aunque no tenga ningún método abstracto en su


cuerpo porque lo ha “heredado” de la interfaz. También ha “heredado” A,B y C

Fundamentos de Programación II 53
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (VIII)
class Software extends Producto {
private String tipo;
public Software (char codigo, String descripcion, String tipo){
super(codigo, descripcion);
this.tipo=tipo;
}
public String getTipo(){
return tipo;
}
public void cambiarTipo(String nuevoTipo){
tipo=nuevoTipo;
}
public double calcularPrecio(){
double resultado;
if (codigo=='B') Método heredado de Producto que a
resultado=B; su vez lo heredó de la interfaz
else
resultado=C;
if (tipo=="ProgramaJuegos") //mejor tipo.equals("ProgramaJuegos")
resultado=resultado*1.05;
return resultado;
}

Fundamentos de Programación II 54
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (IX)

public String toString(){


return "Software";
}

}//fin Software

Fundamentos de Programación II 55
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (X)
class Hardware extends Producto {
private boolean periferico;
public Hardware (char codigo, String descripcion,
boolean periferico){
super(codigo, descripcion);
this.periferico=periferico;
}
public boolean getPeriferico(){
return periferico;
}
public void cambiaPeriferico(boolean nuevoPeriferico){
periferico=nuevoPeriferico;
}
public double calcularPrecio(){
double resultado;
if (codigo=='A') Método heredado de Producto que a
resultado=A; su vez lo heredó de la interfaz
else
resultado=B;
if (periferico==true)
resultado=resultado*1.10;
return resultado;
}

Fundamentos de Programación II 56
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (XI)
public String toString(){
return "Hardware";
}

}//fin Hardware

Fundamentos de Programación II 57
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (XII)
c) Programa Principal: Creación de objetos

class Principal{
public static void main (String [] args){
Software obj1=new Software('C',"Juego de Rol", "ProgramaJuegos");
Hardware obj2=new Hardware('A', "ordenador“,false);
System.out.printf("El precio del producto %c es %.2f."
+ "\nEl producto es de tipo %s y su descripcion %s",
obj1.getCodigo(), obj1.calcularPrecio(),
obj1.getTipo(),obj1.getDescripcion());

System.out.printf("\nEl precio del producto %c es %.2f."


+ "\nEs un periferico %b y su descripcion %S\n",
obj2.getCodigo(),obj2.calcularPrecio(),

obj2.getPeriferico(),obj2.getDescripcion()); }//fin main


}//fin clase Principal

%S escribe la cadena en mayúsculas

Fundamentos de Programación II 58
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (XIII)
c) Programa Principal: Creación de objetos. Uso de polimorfismo

class Principal{
public static void main (String [] args){
Producto [] producto=new Producto [2];

Software obj0=new Software('C',"Juego de Rol", "ProgramaJuegos");


Hardware obj1=new Hardware('A', "ordenador“,false);

producto[0]=obj0;
producto[1]=obj1;

Fundamentos de Programación II 59
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (XIV)
for (int i=0; i<producto.length;i++){
System.out.printf("\nEl precio del producto %c es %.2f"
+ " y su descripcion %s",
producto[i].getCodigo(),
producto[i].calcularPrecio(),
producto[i].getDescripcion());

if (producto[i].toString().equals("Software")) {

System.out.printf("\nEl producto es de tipo %s",


((Software)producto[i]).getTipo());
}
else {
System.out.printf("\nEs un periferico? %b\n",
((Hardware)producto[i]).getPeriferico());
}
}//fin for
}//fin main
}//fin clase Principal

Fundamentos de Programación II 60
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 16 (XV)
Explicación:

- Creamos dos objetos uno Software y otro Hardware.


- Creamos una matriz polimórfica que almacena los dos productos distintos.
- Al hacer las asignaciones producto[0]=obj0; producto[1]=obj1; estamos haciendo dos
asignaciones polimórficas.
- Usando los elementos de la matriz polimórfica podemos invocar a los métodos que
están definidos en la clase Producto.
- Sin embargo, los métodos getTipo() y getPeriferico() son métodos específicos de las
clases hijas por lo que no se puede usar una referencia polimórfica para invocarlos.
Necesitamos invocarlos usando el objeto correspondiente a cada clase. Para ello
usamos un molde sobre la referencia de producto, averiguando previamente a que
tipo de objeto se está refiriendo producto

En lugar de usar el método toString para averiguar de qué clase es el objeto que
estamos tratando se puede usar el operador de Java instanceof.

if (producto[i] instanceof Software)

Usando instanceof no hace falta sobrescribir en las clases Software y Hardware el


método toString.

-Uso del método get_algo para usar el polimorfismo realmente

Fundamentos de Programación II 61
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (I)
Se pretende automatizar el sistema de una empresa dedicada al alquiler de viviendas.
Los tipos de viviendas que la empresa ofrece son pisos y chalets. De todas las
viviendas se registra su identificador (un valor entero), metros cuadrados y precio
mensual de alquiler. De los pisos se debe saber si están amueblados y el año de
construcción. Por otra parte, de los chalets se debe saber si tienen piscina. Para cada
tipo de vivienda también se desea conocer el nombre y DNI de los tres últimos
inquilinos. Se pide:

a) Dibujar el diagrama de clases indicando qué clases hay, la relación entre ellas y los
miembros (atributos y métodos) de cada clase usando notación UML. Considere
Inquilino como una clase
b) Implementar en Java todas las clases resultantes del diagrama. Todas las clases
deben implementar métodos de consulta para cada variable de ejemplar.
c) Escribir un programa principal en Java donde en una única matriz se guarde un
objeto piso y uno chalet. Posteriormente, se debe consultar usando esa matriz el
nombre y DNI de cada uno de los tres últimos inquilinos que ha tenido esa vivienda.

Fundamentos de Programación II 62
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (II)
a)Dibujar el diagrama de clases indicando qué clases hay, la relación entre ellas y los
miembros (atributos y métodos) de cada clase usando notación UML. Considere
Inquilino como una clase.

Identificamos 4 clases: Vivienda, Piso y Chalet relacionadas por herencia e Inquilino


relacionada con Vivienda por asociación

Fundamentos de Programación II 63
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (III)
- Atributos y métodos de las 4 clases

Fundamentos de Programación II 64
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (IV)
- Atributos y métodos de las 4 clases

Fundamentos de Programación II 65
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (V)
b) Implementación de las clases

class Inquilino{
private String nombre;
private String DNI;

public Inquilino (String n, String d){


nombre=n;
DNI=d;

public String get_nombre(){


return nombre;
}
public String get_DNI(){
return DNI;
}
}

Fundamentos de Programación II 66
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (VI)
class Vivienda{
protected int identificador;
protected double metros;
protected double precio;
protected Inquilino [] Inquilinos;

public Vivienda (int id, double m, double p,


Inquilino [] matriz){
identificador=id;
metros=m;
precio=p;
Inquilinos=matriz;
}
public int get_identificador(){
return identificador;
}
public double get_metros(){
return metros;
}
public double get_precio(){
return precio;
}
Fundamentos de Programación II 67
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (VII)
public String get_nombre_inquilino (int i){
return Inquilinos[i].get_nombre();
}
public String get_DNI_inquilino (int i){
return Inquilinos [i].get_DNI();
}
}//fin clase Vivienda

Fundamentos de Programación II 68
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (VIII)
class Piso extends Vivienda{
private boolean amueblado;
private int anio;

public Piso (int id, double m, double p,


Inquilino [] matriz, boolean am, int anio){

super (id,m, p, matriz);


amueblado=am;
this.anio=anio;
}
public boolean get_amueblado(){
return amueblado;
}
public int get_anio(){
return anio;
}

Fundamentos de Programación II 69
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (XI)
class Chalet extends Vivienda{
private boolean piscina;
public Chalet (int id, double m, double p,
Inquilino [] matriz, boolean pisci){

super (id,m, p, matriz);


piscina=pisci;
}
public boolean get_piscina (){
return piscina;
}
}//fin clase Chalet

Fundamentos de Programación II 70
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (X)
c) Principal

class Principal{
public static void main( String args[]){
Inquilino [] matriz1= new Inquilino[3];
Inquilino [] matriz2= new Inquilino[3];

matriz1 [0]= new Inquilino ("ana", "33333");


matriz1 [1]= new Inquilino ("juan", "3334");
matriz1 [2] = new Inquilino ("tere","223");
matriz2 [0]= new Inquilino ("almudena", "23333");
matriz2 [1]= new Inquilino ("javier", "2334");
matriz2 [2] = new Inquilino ("tina","323");

Fundamentos de Programación II 71
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 17 (XII)
Vivienda [] viviendas= new Vivienda[2];
viviendas[0]= new Piso (3, 95.5, 10000.0, matriz1,
true, 1990);
viviendas[1]= new Chalet (4, 100.6, 10000, matriz2,
true);
for (int i=0; i<=viviendas.length-1; i++){
for (int j=0; j<=2; j++){
System.out.print(
viviendas[i].get_nombre_inquilino(j) + " ");
System.out.print(
viviendas [i].get_DNI_inquilino (j)+ " " );
System.out.println();
}
System.out.println();
}
}// fin main

}//fin clase Principal

Fundamentos de Programación II 72
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 18 (I)
¿Qué imprime el siguiente programa?

abstract class Uno { Método abstracto devolver_suma


protected int d1,d2;
abstract public int devolver_suma (int x,int y);
}
class Dos extends Uno {
public int devolver_suma(int x,int y) {
d1=x+3;
d2=y+3; Clase Dos implementa devolver_suma de Uno
return d1+d2;
}
}
class Tres extends Dos {
public int devolver_suma(int x,int y) {
d1=x-3;
d2=y-3; Clase Tres sobrescribe devolver_suma de Dos
return d1+d2;
}
public int devolver_suma(int x,int y, int i, int j) {
d1=x-i;
d2=y-j;
return d1+d2; Sobrecarga del método devolver_suma. Este
} método sólo existe en la clase Tres
}

Fundamentos de Programación II 73
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 18 (II)
class Principal {
public static void main(String [] args) {
int c=0,d=0;
Uno []lista=new Uno[2]; Matriz con referencias
lista [0]= new Dos(); polimórficas de clase Uno
lista [1]= new Tres();
for (int i=0; i<2; i++){
d=lista[i].devolver_suma(10,10);
System.out.printf("d=%d \n",d);
c=lista[i].devolver_suma(10,10,5,5);
System.out.printf("c=%d \n",c);
}
}
}

¡Error! No se puede usar una referencia polimórfica de la


clase Uno con un método no definido en la clase Uno. El
método devolver_suma(int,int,int,int) no está definido en
la clase Uno, sólo en la clase Tres
Fundamentos de Programación II 74
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 18 (III)
Posible solución: Invocar al método devolver_suma (int,int,int,int) con sólo lista[1]
que se refiere a un objeto de clase Tres. lista[0] no es un objeto de clase Tres
for (int i=0; i<2; i++){
d=lista[i].devolver_suma(10,10);
System.out.printf("d=%d \n",d);
}
c=lista[1].devolver_suma(10,10,5,5);
System.out.printf("c=%d \n",c);

¡Error! Tenemos el mismo problema, lista[1] es una


referencia de clase Uno y el método
devolver_suma(int,int,int,int) no está definido en la
clase Uno, sólo en la clase Tres

No hemos solucionado nada.


Para solucionar el problema tenemos dos opciones:
a) Usar un molde de tipo(clase) Tres sobre lista[1] que
es de clase Uno
b) Crear un objeto de clase Tres y usar el método con ese
objeto

Fundamentos de Programación II 75
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 18 (IV)
a) Usar un molde de tipo(clase) Tres sobre lista[1] que es de clase Uno

for (int i=0; i<2; i++){


d=lista[i].devolver_suma(10,10);
System.out.printf("d=%d \n",d);
}
c=((Tres)lista[1]).devolver_suma(10,10,5,5);
System.out.printf("c=%d \n",c);
b) Crear un objeto de clase Tres y usar el método con ese objeto
Uno []lista=new Uno[2];
lista [0]= new Dos();
lista [1]= new Tres();
Tres obj=new Tres();
for (int i=0; i<2; i++){
d=lista[i].devolver_suma(10,10);
System.out.printf("d=%d \n",d); Solucionado el
} problema, el
c=obj.devolver_suma(10,10,5,5); programa imprimiría:
System.out.printf("c=%d \n",c);

d=26
d=14
c=10

Fundamentos de Programación II 76
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 19 (I)
¿Por qué da error el siguiente programa?
class A {
private
protected intint
l=2;l=2;
public int get_l(){ Solución: Cambiar el
return l; modificador de l de private
} a protected
}
class B extends A {
public int calcular_m(int x) { ¡Error! La variable l es
int m=l+x;
return m; privada, no se hereda. Por
} tanto, no se puede usar en
} la clase B
class Principal {
public static void main(String [] args) {
int l,m;
B o1=new B();
¿Existe otra solución sin modificar el modificador de
l=o1.get_l();
visibilidad de l?
System.out.printf("l=%d \n",l);
m=o1.calcular_m(2);
System.out.printf("m=%d \n",m);
} SI
}
Usar en la clase B, el método get_l() que se hereda al
ser público.

Fundamentos de Programación II 77
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 19 (II)
class A {
private int l=2;
public int get_l(){
return l;
}
}
class B extends A {
public int calcular_m(int x) {
int m=get_l()+x;
return m;
}
}
class Principal {
public static void main(String [] args) {
int l,m;
B o1=new B();
l=o1.get_l();
System.out.printf("l=%d \n",l);
m=o1.calcular_m(2);
System.out.printf("m=%d \n",m); Solucionado el
}
} problema, el
programa imprimiría:

l=2
m=4

Fundamentos de Programación II 78
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 20 (I)
¿Qué imprime el siguiente programa?
class Uno {
protected int d1,d2;
public int get_suma(){
return d1+d2;
}
}
class Dos extends Uno {
public void cambiar_ds(int x,int y) {
d1=x+3;
d2=y+3;
}
}
class Tres extends Dos {
public void cambiar_ds(int x,int y, int i, int j) {
d1=d1+x-i;
d2=d2+y-j;
}
}

Clase Tres hereda el método cambiar_ds y lo


sobrecarga.
En clase Tres hay dos métodos cambiar_ds:
cambiar_ds(int,int) heredado de clase Dos
cambiar_ds(int,int,int,int) sobrecarga el heredado

Fundamentos de Programación II 79
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 20 (II)
class Principal {
public static void main(String [] args) {
int c,d;
Dos obj2=new Dos();
Tres obj3=new Tres();
d1=x+3=5; d2=y+3=5
Invocamos al método de la clase
obj2.cambiar_ds(2,2); Dos
Invocamos al método en la clase
d1=x+3=6;d2=y+3=6
obj3.cambiar_ds(3,3); Tres heredado de la clase Dos
Invocamos al método sobrecargado
d1=d1+x-i=6+10-7=9
obj3.cambiar_ds(10,9,7,8);
en la clase Tres
d2=d2+y-j=6+9-8=7
d=obj2.get_suma();
c=obj3.get_suma(); d1+d2=10 d1+d2=16
System.out.printf("d=%d \nc=%d\n",d,c);
}
}
d=10
c=16

Fundamentos de Programación II 80
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 21 (I)
¿Cuál es el resultado del siguiente programa?
class Principal {
public static void main(String [] args) {
double cantidad_ini,cantidad_inc;
Coche c1=new Coche();
cantidad_ini=c1.devolver_cantidad();
cantidad_inc=c1.cambiar_cantidad(20.17);
System.out.printf("%.1f %.1f",cantidad_ini,
cantidad_inc);
}
}
class Vehiculo {
private double c=10.11;
public double devolver_cantidad(){
return c;
}
}
class Coche extends Vehiculo {
public double cambiar_cantidad(double p){
return devolver_cantidad()+p;
}
}
Fundamentos de Programación II 81
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 21 (II)
a) 10,1 30,3
b) 10,1 30,2
c) Error: No se puede usar el método devolver_cantidad en la clase Coche
porque la variable c es private
d) Error: No se puede invocar directamente en el return de la clase Coche al
método devolver_cantidad

Fundamentos de Programación II 82
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 22
¿Cuál es el error del siguiente programa?

interface Constantes {
double PI=3.141593;
double e=2.718282;
double FI=1.618034;
}
interface Metodos {
void metodoA () ;
double metodoB ();
}
class Calculos implements Metodos, Constantes {
public double metodoB () {
return PI*e*FI;
}
}

a) La clase Cálculos no puede implementar más de una interfaz


b) Los métodos de la interfaz Metodos deben ser públicos
c) La clase Calculos debe ser abstract
d) No hay ningún error
Fundamentos de Programación II 83
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 23 (I)
¿Cuál es el resultado del siguiente programa?

class Ejercicio {
public static void main (String [] args) {
A a1= new A(7);
A a2= new B(9);
B b1= new B(10);
System.out.print(a1.get_p1()+" ");
System.out.print(a2.get_p1()+" ");
System.out.print(b1.get_p1()+" ");
a1=b1;
System.out.print(b1.get_p2()+" ");
}//fin main
}

Fundamentos de Programación II 84
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 23 (II)
final class A{ Nota: Las variables de ejemplar deben
static int p1=0; llevar el atributo de visibilidad. En
public A (int v){ este caso no lo llevan, Esto implica
p1=v; que son vistas en clases que estén en
} el mismo paquete, pero no implica
public int get_p1(){ que las vean las clases hijas (si éstas
return p1; no están en el mismo paquete). En el
} caso de la clase B debe ser private
}
class B extends A {
int p2=0;
a) 10 10 10 20
public B(int p){
b) 7 9 10 20
super(p);
c) Se produce un error porque las
p2=p;
variables de las clases no tienen
}
visibilidad declarada
public int get_p2(){
d) Se produce un error porque una
return p2+p1;
clase declarada como final no se
}
puede heredar
}
Si se elimina final: 10 10 10 20
Fundamentos de Programación II 85
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 24 (I)
¿Cuál es el resultado del siguiente programa?

class Principal {
public static void main (String [] args){
Ordenador orde=new Portatil (34,870.12, 2.3);;
System.out.printf("Codigo: %d \nPrecio_total: %.2f",
orde.devuelvecodigo(),
orde.calcula_preciototal(5));
}
}//fin clase Principal

Fundamentos de Programación II 86
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 24 (II) Variables privadas. No
class Ordenador { se heredan. Son
private int codigo; visibles a través de los
private double precio; métodos de consulta
public Ordenador (int codigo,double precio){
this.codigo=codigo;
this.precio=precio;
}
public int devuelvecodigo(){
return codigo;
}
public double devuelveprecio(){
return precio;
}
final public double calcula_preciototal(int unidades){
return precio*unidades;
}
}//fin clase Ordenador

Fundamentos de Programación II 87
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 24 (III)
class Portatil extends Ordenador {
private double peso;
public Portatil(int codigo, double precio,double peso) {
super (codigo,precio);
this.peso=peso;
}
public double devuelvepeso(){
return peso;
}
public double calcula_preciototal(int unidades){
return devuelveprecio()*unidades*.90;
}
}//clase Portatil

¡ERROR!

El método calcula_preciototal está declarado como final, por tanto, no


se puede sobrescribir

Fundamentos de Programación II 88
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (I)
Una empresa de envío de paquetes tiene varias sucursales en todo el país.
Cada sucursal está definida por su número de sucursal, dirección y ciudad.
Además, conviene distinguir si la sucursal es Principal o Secundaria. En
caso de ser sucursal Principal se debe saber el número de sucursales
secundarias que dependen de ella y en el caso de la Secundaria es necesario
saber el nombre de la sucursal de la que depende. Para calcular el precio que
cuesta enviar cada paquete, las sucursales tienen en cuenta el peso del
paquete y la prioridad, sabiendo que se cobra 1 euro por kilo, 10 euros más
si la prioridad es alta y 20 si es Express. Cada paquete enviado tendrá un
número de referencia.

Fundamentos de Programación II 89
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (II)
-Construya un diagrama UML que indique la relación entre las clases.
-Cree un diagrama UML para cada clase que incluya todos sus miembros.
-Implemente las clases correspondientes añadiendo métodos para consultar
todos los atributos y para modificar el peso y la prioridad de los paquetes.
-Método main donde se cree un objeto sucursal Secundaria que dependa de
una sucursal Principal. El objeto Sucursal Secundaria deberá crearse
mediante una referencia polimórfica.
-Imprimir el precio y el peso de los paquetes que se reciban en dicha
sucursal.
-La información de los paquetes deberá guardarse en una matriz.
-Controlar que la prioridad del paquete sea 0, 1 ó 2.
- Tanto los datos de la sucursal como los de los paquetes deberán
introducirse por teclado.
Nota: No considere que paquete es un atributo de sucursal.

Fundamentos de Programación II 90
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (III)
1.Diagrama UML de relaciones entre clases
2.Diagrama UML de cada clase con atributos y métodos

Paquete
-referencia:int
-peso:double
-DNI:String
-prioridad:int
+Paquete (referencia:int, peso:double, DNI:String,
pri:int)
+devolver_referencia():int
+devolver_peso ():double
+devolver_DNI():String
+devolver_prioridad():int
+cambiar_peso(peso:double):void
+cambiar_prioridad(pri:int):void

Fundamentos de Programación II 91
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (IV)
Sucursal
-numero:int
-direccion:String
-ciudad: String
+Sucursal (num:int, dire:String, ciudad:String)
+devolver_numero ():int
+devolver_direccion():String
+devolver_ciudad():String
+calcular_precio(t:Paquete):double

Principal
-numeroS:int
+Principal (num:int, dire:String, ciudad:String, nS:int)
+devolver_numeroS ():int

Secundaria
-nombreP:String
+Secundaria (num:int, dire:String, ciudad:String, nP:String)
+devolver_nombreP ():String

Fundamentos de Programación II 92
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (V)
3. Implementación de las clases

class Paquete{

private int referencia;


private double peso;
private String DNI;
private int prioridad; // 0 normal, 1 alta, 2 express

public Paquete (int r, double peso, String d, int p){


referencia=r;
this.peso=peso;
DNI=d;
prioridad=p;
}

Fundamentos de Programación II 93
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (VI)
public double get_peso (){
return peso;
}
public int get_prioridad (){
return prioridad;
}
public void set_peso (double p){
peso=p;
}

public void set_prioridad (int prio){


prioridad=prio;
}
}//fin clase Paquete

Fundamentos de Programación II 94
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (VII)
class Sucursal{
private int numero;
private String direccion;
private String ciudad;

public Sucursal ( int n, String d, String c){


numero=n;
direccion=d;
ciudad=c;
}
public int getnumero(){
return numero;
}
public String getdireccion(){
return direccion;
}
public String getciudad(){
return ciudad;
}

Fundamentos de Programación II 95
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (VIII)
public double calcula_precio (Paquete t){

double precio;
precio= t.get_peso();

if (t.get_prioridad()==1){ //prioridad alta


precio=precio+10;
}
if (t.get_prioridad() ==2){ //prioridad express
precio=precio+20;
}

return precio;
}
}//fin clase Sucursal

Fundamentos de Programación II 96
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (IX)
class SPrincipal extends Sucursal{

private int numero;

public SPrincipal (int n, String d, String c, int nu){


super (n, d,c);
numero=nu;
}

public int getnumero (){


return numero;
}

} //fin clase Sprincipal

Fundamentos de Programación II 97
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (X)
class Secundaria extends Sucursal{

private String nombrePrincipal;

public Secundaria (int n, String d, String c,


String nombre){

super(n, d,c);

nombrePrincipal=nombre;
}

public String getnombrePrincipal(){


return nombrePrincipal;
}

}//fin clase Secundaria

Fundamentos de Programación II 98
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (XI)
class Ejecicio {
public static void main (String [] args){
Scanner lectura=new Scanner (System.in);
Sucursal s1;
Paquete [] paquetes;
boolean logica;
System.out.println ("Introduzca los datos de la sucursal
Secundaria");
System.out.println("Numero?");
int n=lectura.nextInt();
System.out.println("Direccion?");
String dir=lectura.next();
System.out.println("Ciudad?");
String ciu=lectura.next();
System.out.println("SucursalPrincipal?");
String sp=lectura.next();
s1=new Secundaria (n,dir,ciu,sp);

Fundamentos de Programación II 99
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (XII)

System.out.println(“¿Cuántos paquetes se han recibido en


la sucursal?");
int npaq=lectura.nextInt();
paquetes=new Paquete [npaq];
System.out.printf ("Introduzca los datos de los %d
paquetes\n",npaq);

for (int i=0; i<npaq;i++){


System.out.println("Referencia?");
int ref=lectura.nextInt();
System.out.println("Peso?");
double peso=lectura.nextDouble();
System.out.println("DNI?");
String dni=lectura.next();

Fundamentos de Programación II 100


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 25 (XIII)
do {
logica=false;
System.out.println("Prioridad?");
int pri=lectura.nextInt();
if (pri>=0&&pri<=2){
paquetes[i]=new Paquete (ref,peso,dni,pri);
}
else{
System.out.println("Solo hay prioridad 0 1 2");
logica=true;
}
}while (logica==true);
}//fin for de lectura de paquetes
for (int i=0;i<npaq;i++){
System.out.println("el precio del paquete es: "+
s1.calcula_precio(paquetes[i]));
System.out.println("el peso de este paquete es: "+
paquetes[i].get_peso());
}
}//fin main
}//fin clase Ejercicio
Fundamentos de Programación II 101
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (I)
En una mediateca tenemos disponibles dos tipos diferentes de
documentos: Libros y DVD’s (video). Todos los documentos se
caracterizan por una fecha de edición, un título, un valor nominal (en
euros), y un atributo que indica si el documento está prestado o no. A su
vez, los libros deben incluir el autor y los DVD’s el director de la película.
Si una vez prestado un documento no se devuelve en la fecha debida
existe una penalización en todos ellos. En los libros la penalización se
obtiene como un 5% de su valor nominal. En los DVD’s es un 6% del valor
nominal más un valor fijo de 2 euros. A su vez, los socios de la mediateca
se caracterizan por su nombre y número de socio. Los socios de la
mediateca pueden sacar en préstamo un máximo de n documentos. En
caso de retraso en la devolución de los documentos prestados se aplica
al socio una penalización obtenida como la suma de las penalizaciones de
cada documento prestado.

Fundamentos de Programación II 102


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (II)
Se pide:

a) Dibujar el diagrama de clases indicando las relaciones entre las


mismas.
b) Dibujar para cada clase el diagrama UML indicando los miembros que
hay en cada una. Debe incluir todos los métodos que sean necesarios
para la resolución del ejercicio.
c) Implementar en Java dichas clases.
d) Implementar un programa principal que defina dos documentos de
tipos distintos. Los documentos se inicializarán directamente en el
programa principal. A continuación cree un objeto de clase socio
(inicializado también directamente en el main) que saque en préstamo los
dos documentos anteriores. Finalmente, imprima los datos del socio así
como la penalización correspondiente por un retraso en la devolución de
los dos documentos. Utilice una matriz para almacenar los objetos
documento haciendo uso del polimorfismo.

Fundamentos de Programación II 103


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (III)

0..n

-La relación es 1 a 0..n; un Socio tiene entre 0 y un máximo de n


documentos.
-No es 1 a * (esto implicaría un número indeterminado de documentos).

Fundamentos de Programación II 104


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (IV)

Documento
#fecha:String
#titulo:String
#valor:double
#prestado:boolean
+Documento (fecha:String, titulo:String, valor:double)
+devolverFecha():String
+devolverTtitulo():String
+devolverValor():double
+devolverPrestado():boolean
+cambiarPrestado():void
+penalizacion():double

El método penalización es abstracto. Debe indicarse escribiéndolo en


cursiva

Fundamentos de Programación II 105


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (V)

Libro
-autor:String

+Libro (fecha:String, titulo:String, valor:double, autor:String)


+devolverAutor():String
+penalizacion():double

DVD
-director:String

+DVD (fecha:String, titulo:String, valor:double, director:String)


+devolverDirector():String
+penalizacion():double

El método penalización se implementa en estas clases por lo


que debe incluirse el método en el diagrama

Fundamentos de Programación II 106


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (VI)
Socio
-nombre:String
-numero:int
-prestados:[] Documento
+Socio (nombre:String, numero:int, prestados:[]Documento)
+devolverNombre():String
+devolverNumero():int
+penalizacion_total():double

-La relación de asociación es 1 a n. Esto implica que habrá en socio una


matriz de documentos de longitud n.
-Aquí se calcula la penalización_total que tiene que abonar el socio

Fundamentos de Programación II 107


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (VII)
abstract class Documento{
protected String fecha;
protected String titulo;
protected double valor;
protected boolean prestado;
public Documento (String fecha, String titulo, double valor){
this.fecha=fecha;
this.titulo=titulo;
this.valor=valor;
prestado=false;
}
public String devolverFecha(){
return fecha;
}
public String devolverTitulo(){
return titulo;
}
public double devolverValor(){
return valor;
}
public boolean devolverPrestado(){
return prestado;
}
Fundamentos de Programación II 108
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (VIII)
public void cambiarPrestado(){
prestado=!prestado;
}
public abstract double penalizacion();
}//fin clase Documento

class Libro extends Documento{


private String autor;
public Libro(String fecha, String titulo, double valor,
String autor){

super (fecha, titulo, valor);


this.autor=autor;
}
public String devolverAutor(){
return autor;
}
public double penalizacion(){
return valor*0.05;
}
}//fin clase Libro

Fundamentos de Programación II 109


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26 (IX)
class DVD extends Documento{
private String director;
public DVD(String fecha, String titulo, double valor,
String director){

super (fecha, titulo, valor);


this.director=director;
}
public String devolverDirector(){
return director;
}
public double penalizacion(){
return valor*0.06+2.0;
}
}//fin clase DVD

- Si la clase padre tiene un constructor para inicializar sus variable, siempre se usa
super para inicializar las variables del constructor de la clase hija

Fundamentos de Programación II 110


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26(X)
class Socio{
private String nombre;
private int numero;
private Documento[] prestados;
public Socio(String nom, int num, Documento [] prestados){
nombre=nom;
numero=num;
this.prestados=prestados;
for (int i=0; i<prestados.length; i++) {
prestados[i].cambiarPrestado();
}
}
public String devolverNombre(){
return nombre;
}
public int devolverNumero(){
return numero;
}

Fundamentos de Programación II 111


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26(XI)
public double penalizacion_total(){
double valor=0;
for (int i=0; i<prestados.length; i++){
valor+=prestados[i].penalizacion();
}
return valor;
}
}//fin clase Socio

- La penalización total se calcula invocando al método penalización de cada


elemento prestado. El bucle for calcula la penalización total, sumando el valor de
cada penalización annual.

-No tiene sentido que penalización sea una variable de ejemplar de socio. No es una
característica de socio.

-Debe haber un método penalización que devuelva el valor de la suma al método


main. Si usamos toString tendríamos el valor en forma de cadena y puede que no
queramos imprimirlo

Fundamentos de Programación II 112


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 26(XII)
class Mediateca{
public static void main (String [] args){
Documento [] docus=new Documento [2];

docus[0]= new Libro("2/10/2009", "La Odisea", 30.50, "Homero");


docus[1]= new DVD ("3/11/1942", "Vértigo", 20.50,
"A. Hitchcock");

Socio unSocio= new Socio ("I. Caro", 11, docus);

System.out.printf("Nombre:%s\nNº socio:%d\nPenalizacion: %.2f",


unSocio.devolverNombre(),
unSocio.devolverNumero(),
unSocio.penalizacion_total());
}
}//fin clase Mediateca

-Trabajando de esta forma no accedemos a los documentos directamente. Todo se


hace a través de Socio.

Fundamentos de Programación II 113


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (I)
Escriba un programa para una biblioteca que contiene libros y revistas.
Ambas publicaciones tienen un código, un año de publicación y un
atributo prestado. Cuando se crea la publicación, el atributo prestado está
a falso porque la publicación no está prestada. Las revistas tienen un
número y los libros un nombre del autor.
Ambos tipos de publicaciones deben tener métodos de consulta de todos
sus atributos.
Para prevenir posibles cambios en el programa se tiene que implementar
una interfaz que contenga los métodos prestar(), devolver() y prestado().
La clase publicación implementará dicha interfaz.
El programa deberá obtener el número de publicaciones prestadas.
Para ello la clase Principal contendrá dos métodos:
a)un método que cuente las publicaciones prestadas. Dicho método
recibirá como parámetro una lista de las publicaciones existentes en la
biblioteca y devolverá cuántas hay prestadas.
b)el método main que creará una matriz de referencias polimórficas de
tipo publicación, invocará al método con el que se obtiene el número de
publicaciones prestadas e imprimirá el número de publicaciones
prestadas. También se deberá imprimir los datos de todas las
publicaciones. Como ejemplo cree una matriz de 2 libros y 2 revistas y
considere que se prestan un libro y una revista.
Fundamentos de Programación II 114
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (II)
a)Dibujar el diagrama de clases indicando qué clases hay, la relación
entre ellas y los miembros (atributos y métodos) de cada clase usando
notación UML.

b) Implementar en Java todas las clases e interfaces resultantes del


diagrama.

c) Escribir un programa principal en Java en el que se realicen las


operaciones comentadas anteriormente (cálculo de publicaciones
prestadas usando un método específico para tal fin e impresión en el
método main del número de publicaciones prestadas).

Fundamentos de Programación II 115


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (III)
-Relaciones entre clases e interfaz. UML de las clases

Fundamentos de Programación II 116


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (IV)

Fundamentos de Programación II 117


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (V)
-Implementación de la interfaz

interface Prestable {
void prestar();
void devolver();
boolean prestado();
}

Fundamentos de Programación II 118


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (VI)
-Implementación de las clases

class Publicacion implements Prestable {


protected int codigo;
protected String agno;
protected boolean prestado;
public Publicacion (int c, String a){
codigo=c;
agno=a;
prestado=false;
}
public int getcodigo (){
return codigo;
}
public String getagno(){
return agno;
}

Fundamentos de Programación II 119


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (VII)
public boolean prestado(){
return prestado;
}
public void prestar(){
prestado=true;
}
public void devolver(){
prestado=false;
}
public String toString (){
String p;
if (prestado == true)
p = ": Prestada";
else
p = ": Disponible";
return "Publicacion "+codigo+ p+ "\nAño: "+ agno;
}

}//fin clase Publicacion

Fundamentos de Programación II 120


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (VIII)
class Libro extends Publicacion{
private String autor;
public Libro (int c, String a, String autor){
super(c,a);
this.autor=autor;
}
public String getautor(){
return autor;
}
public String toString (){
return super.toString()+ ". Autor del libro: " + autor;
}
}//fin clase Libro

Fundamentos de Programación II 121


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (IX)
class Revista extends Publicacion{
private int numero;
public Revista (int c, String a, int n){
super(c,a);
numero=n;
}
public int getnumero(){
return numero;
}
public String toString (){
return super.toString()+ ". Numero de la revista: " +
numero;
}
}//fin clase Revista

Fundamentos de Programación II 122


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (X)
class Principal {
public static void main (String [] args){
int npres;
Publicacion [] pub=new Publicacion [4];
pub [0]=new Libro(1,"1990","A");
pub [1]=new Libro(2,"1991","B");
pub [2]=new Revista(3,"1992",1);
pub [3]=new Revista(4,"1993",2);
pub[0].prestar();
pub[2].prestar();

System.out.println("Publicaciones en la biblioteca\n");
for (Publicacion p: pub){
System.out.println(p.toString());
}
npres=calcularprestados(pub);
System.out.println(“\nEl numero de publicaciones prestadas
es de: "+npres);
}//fin main

Fundamentos de Programación II 123


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 27 (XI)
public static int calcularprestados(Publicacion [] pub){
int contador=0;
for (int i=0; i<pub.length;i++){
if (pub[i].prestado()==true) contador++;
}
return contador;
}//fin calcularprestados

}//fin clase Principal

Fundamentos de Programación II 124


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 28 (I)
¿Qué imprime el siguiente programa?

class Principal {
public static void main (String [] args){
Rueda r1=new Rueda (16, "R1");
Rueda r2=new Rueda (16, "R1");
Rueda r3=new Rueda (17, "R2");

System.out.println(r1.equals(r3));
System.out.println(r1.equals(r2));
r1=r3;
System.out.println(r1.equals(r3));
}
}//fin clase Principal

Fundamentos de Programación II 125


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 28 (II)

class Rueda {
private int dimension;
private String ID;
public Rueda (int dimension,String ID){
this.dimension=dimension;
this.ID=ID;
}
public int get_dimension(){
return dimension;
}
public String get_ID(){
return ID;
}

Fundamentos de Programación II 126


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 28 (III)
public boolean equals (Object o) {
boolean logica=false;
Método equals() sobrescrito de la clase Object.
if (this==o){ Si no se quiere poner un molde deberíamos
logica=true; sobrecargar el método no sobrescribirlo: public
} boolean equals(Rueda o)
else {
if(this.ID == ((Rueda) o).get_ID() &&
this.dimension==((Rueda)o).get_dimension()) {

logica=true;
}
}
return logica;
}//finMétodo
método equals
equals() sobrescrito de la clase Object.
CuandoRueda
}//fin clase se comparan dos objetos que contienen la misma información
pero son objetos distintos hay que escribir el método equals comparando
todos los atributos.
false Sin embargo cuando dos objetos son el mismo (distintas referencias para
true el mismo objeto) es suficiente con hacer la comparación de la forma
true this==o.

Fundamentos de Programación II 127


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (I)
¿Qué imprime el siguiente programa?

class Producto implements Comparable <Producto> {


int ID;
String nombre;
double precio;

public Producto(int ID,String n, double p) {


this.ID=ID;
nombre=n;
precio=p;
}
public String toString(){
return ID+": "+nombre+" "+precio+" euros";
}
public String get_nombre(){
return nombre;
}
public int get_ID (){
return ID;
}
public double get_precio(){
return precio;
}
Fundamentos de Programación II 128
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (II)
public int compareTo (Producto p){
int res=0;
if (ID>p.get_ID()){
res=1;
}
else {
if (ID<p.get_ID()){
res=-1;
}
}
return res;
}
}

Fundamentos de Programación II 129


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (III)
class Principal {
public static void main (String [] args){

Producto[] productos = {new Producto(21,"Portátil",488.90),


new Producto(8, "Tarjeta gráfica",139.15),
new Producto(12,"Monitor",149.0),
new Producto(13,"Impresora",105.45),
new Producto(4,"Teclado", 500.2) };

System.out.println("Productos sin ordenar");


for (int i=0; i<productos.length;i++){
System.out.println(productos[i].toString());
}

burbuja(productos);

System.out.println("\nOrdenados por ID");


for(Producto p : productos){
System.out.println(p.toString());
}
}

Fundamentos de Programación II 130


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (IV)
public static void burbuja (Producto [ ] p) {
Producto aux;
int longitud;
longitud=p.length;

for (int i=0; i<longitud-1; i++) {


for (int j=0; j< (longitud-1-i); j++) {
if (p[j].compareTo(p[j+1])>0) {
aux=p[j];
p[j]=p[j+1];
p[j+1]=aux;
}
}
}
}
} //fin clase Principal

Fundamentos de Programación II 131


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (V)
Si ejecutamos el programa se imprime:

Productos sin ordenar


21: Portátil 488.9 euros
8: Tarjeta gráfica 139.15 euros
12: Monitor 149.0 euros
13: Impresora 105.45 euros
4: Teclado 500.2 euros

Ordenados por ID
4: Teclado 500.2 euros
8: Tarjeta gráfica 139.15 euros
12: Monitor 149.0 euros
13: Impresora 105.45 euros
21: Portátil 488.9 euros

El programa ordena en orden creciente (de menor a mayor) por código de


identificación (ID) una serie de productos por contenidos en una matriz de objetos
de clase Producto. El método de ordenación utilizado es el método de ordenación
por intercambio, también llamado de la burbuja.

Fundamentos de Programación II 132


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (VI)
Analicemos el programa:

1.Método (algoritmo) de ordenación por intercambio (o de la burbuja):

El algoritmo se basa en el principio de comparar pares de elementos


adyacentes e intercambiarlos entre sí hasta que estén todos ordenados.
Veamos un ejemplo de ordenación en orden creciente.

Secuencia de pasos (primera iteración)


50 15 56 14 35 1
15 50 56 14 35 1
15 50 56 14 35 1
15 50 14 56 35 1
15 50 14 35 56 1
15 50 14 35 1 56  Resultado de la primera iteración

Como podemos observar, el último número ya está en su sitio. Ahora


repetiríamos con la sublista sin ordenar (todos los elementos menos el
último) y así hasta un total de cinco pasadas.

Esto se plasma en el siguiente código en Java:

Fundamentos de Programación II 133


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (VII)
public static void burbuja (Producto [] p) {
Producto aux; //Matriz auxiliar para hacer el intercambio
int longitud;
longitud=p.length;

for (int i=0; i<longitud-1; i++) {


for (int j=0; j< (longitud-1-i); j++) {
if (p[j].compareTo(p[j+1])>0) { //Se comparan elementos
aux=p[j];
p[j]=p[j+1];
p[j+1]=aux;
}
}
}
}

Existen varios algoritmos más eficientes que esté. Los más básicos son el de
selección y el de insercción. Hay varios otros más eficientes que daréis en 2º
(Quicksort por ejemplo)

Fundamentos de Programación II 134


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (VIII)
2. Método compareTo()

El método de la burbuja compara los valores de los elementos de la matriz, para


ordenar de menor a mayor, usando el método compareTo() implementado en la
clase Producto.

public int compareTo (Producto p){


int res=0;
if (ID>p.get_ID()){
res=1;
}
else {
if (ID<p.get_ID()){
res=-1;
}
}
return res;
}

El método compareTo() está definido en de la interfaz Comparable y


puede ser sobrescrito (al igual que hacíamos con equals() y toString() de
la clase Object). En este caso está escrito para que compare enteros.
Fundamentos de Programación II 135
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (IX)
La clase Producto implementa la interfaz Comparable. De esta manera nos
vemos obligados a sobrescribir el método compareTo(). El método
compareTo() recibe un objeto de la clase Producto (por ello debemos
hacer:
class Producto implements Comparable <Producto>

manejando así la interfaz con genéricos.

Este método compara el objeto en el que estoy con el objeto que se le


pasa al método. Devuelve un entero negativo, cero o positivo si el objeto
es menor, igual o mayor que el objeto que se le pasa (en el orden natural
de los tipos de datos). En este caso se sobrescribe completamente para
comparar enteros. El método equals() sólo devuelve true o false si dos
objetos son iguales o no. No sirve para hacer ordenaciones.

Existe un método compare() de la intefaz Comparator para comparar dos


objetos que se pasan como argumentos.

Fundamentos de Programación II 136


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (X)
Si no se usan genéricos habría que usar un molde en el método
compareTo() .

class Producto implements Comparable { //Se quita <Producto>

El método compareTo() quedaría:

public int compareTo (Object p){


int res=0;
if (ID>((Producto)p).get_ID()){
res=1;
}
else {
if (ID<((Producto)p).get_ID()){
res=-1;
}
}
return res;
}
No se pasa un objeto de clase Producto sino de clase Object y habría que
usar en el código un molde.
Fundamentos de Programación II 137
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (XI)
3. Bucle for

En el método main hay dos bucles for: el bucle tradicional

for (int i=0; i<productos.length;i++){


System.out.println(productos[i].toString());
}

y el bucle mejorado usado cuando se itera en matrices (y colecciones)

for(Producto p : productos){
System.out.println(p.toString());
}

la variable p de clase Producto tiene el valor actual de la matriz productos

Por ejemplo si fuera una matriz de enteros llamada números


for (int item : numeros) {
System.out.println("Valor: "+ item);
}

item da el valor actual de la matriz (que es lo que se va imprimiendo)


Fundamentos de Programación II 138
© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (XII)
4. Método de la burbuja usando genéricos

Se puede rescribir el método de ordenación para que acepte cualquier


tipo de matriz para ordenar no sólo una matriz de Productos. El método
sería:
public static <T extends Comparable> void burbuja (T [] p) {
T aux;
int longitud;
longitud=p.length;
for (int i=0; i<longitud-1; i++) {
for (int j=0; j< (longitud-1-i); j++) {
if (p[j].compareTo(p[j+1])>0) {
aux=p[j];
p[j]=p[j+1];
p[j+1]=aux;
}
}
}
}
donde se ha sustituido Producto por T (genérico). Este método invocará
al método compareTo() sobrescrito en la clase que represente a los
objetos a ordenar.

Fundamentos de Programación II 139


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (XIII)
La cabecera del método en principio sería:

public static <T> void burbuja (T [] p) { //sin extends Comparable

pero el programa así no funciona.

Se debe usar

public static <T extends Comparable> void burbuja (T [] p)

<T extends Comparable> sirve para decirle al compilador que el


método compareTo() va a recibir solo parámetros de clases que
implementen la interfaz Comparable (en este caso elementos de clase
Producto). Si no, el compilador no sabe a priori si va a recibir un
argumento válido y da error de compilación.

extends en lugar de implements (es así con los genéricos)

Fundamentos de Programación II 140


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (XIV)
b) ¿Y si el método compareTo() se sustituye por el siguiente?

public int compareTo(Producto p){


return nombre.compareTo(p.get_nombre());
}

La salida sería la siguiente:

Ordenados por nombre


13: Impresora 105.45 euros
12: Monitor 149.0 euros
21: Portátil 488.9 euros
8: Tarjeta gráfica 139.15 euros
4: Teclado 500.2 euros

porque se ordenaría por nombre.

La clase String tiene sobrescrito el método compareTo() por lo que lo


llamamos directamente y no hace falta implementarlo.

Fundamentos de Programación II 141


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 29 (XV)
c) ¿Y si el método compareTo() se sustituye por el siguiente?

public int compareTo(Producto p){


return new Double(precio).compareTo(new Double(p.get_precio()));
}

Se imprimiría:

Ordenados por precio


13: Impresora 105.45 euros
8: Tarjeta gráfica 139.15 euros
12: Monitor 149.0 euros
21: Portátil 488.9 euros
4: Teclado 500.2 euros
En este caso se ordena por precio.

Se usa el método compareTo() de la clase contenedora Double,


convirtiendo nuestro tipo primitivo double a un objeto Double. Se puede
hacer igual que el caso del ID pero cuidado con la precisión de un tipo
real.

Fundamentos de Programación II 142


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 30 (I)
Escribir un programa en Java que ordene una serie personas por edad (de
mayor a menor) usando el método de ordenación por intercambio. Las
personas estarán contenidas en una matriz de objetos de clase Persona.
Esta clase tendrá dos atributos, nombre y edad, además de los métodos
necesarios para resolver el ejercicio. El método de ordenación deberá ser
genérico para que acepte cualquier tipo de matriz de objetos. Repetir el
programa para ordenar ahora por nombre (en orden alfabético de mayor a
menor).

Este ejercicio se resuelve de la misma forma que el ejercicio 31


sustituyendo Producto por Persona (con los atributos y métodos
correspondientes) y usando el método de la burbuja con genéricos.
Además al querer ordenar de mayor a menor hay que cambiarle > por < en
la comparación que se hace en el bucle interno del método de la burbuja

Fundamentos de Programación II 143


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 30 (II)
class Persona implements Comparable <Persona> {
int edad;
String nombre;

public Persona(String n,int e) {


edad=e;
nombre=n;
}
public String toString(){
return nombre+" tiene "+edad+" años";
}
public String get_nombre(){
return nombre;
}
public int get_edad (){
return edad;
}

Fundamentos de Programación II 144


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 30 (III)
public int compareTo (Persona p){
int res=0;
if (edad>p.get_edad()){
res=1;
}
else {
if (edad<p.get_edad()){
res=-1;
}
}
return res;
}

Fundamentos de Programación II 145


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 30 (IV)
class Principal {
public static void main (String [] args){
Persona[] personas = {
new Persona("Adela", 20),
new Persona("Teresa",15),
new Persona("Pedro",30),
new Persona ("Paco", 28)};

System.out.println("Personas sin ordenar");


for (int i=0; i<personas.length;i++){
System.out.println(personas[i].toString());
}
burbuja(personas);
System.out.println("\nOrdenados por edad");
for(Persona p : personas){
System.out.println(p.toString());
}
}

Fundamentos de Programación II 146


© A. Niño-Universidad de Castilla-La Mancha
Ejercicio 30 (V)
public static <T extends Comparable> void burbuja (T [] p) {
T aux;
int longitud;
longitud=p.length;
for (int i=0; i<longitud-1; i++) {
for (int j=0; j< (longitud-1-i); j++) {
if (p[j].compareTo(p[j+1])<0) { //ordena de mayor a menor
aux=p[j];
p[j]=p[j+1];
p[j+1]=aux;
}
} // Fin for j
} // Fin for i
}
}

Para ordenar por nombre basta sustituir el método compareTo() del programa
anterior por:

public int compareTo(Persona p){


return nombre.compareTo(p.get_nombre());
}

Fundamentos de Programación II 147


© A. Niño-Universidad de Castilla-La Mancha

También podría gustarte