Está en la página 1de 51

;>

xra dr
rchir.o

los
de

s. ivl Uesfe

in

la po_

s despus

re mucha
:1 mismo o.

Flerene ia y polimcfl'fisrno

:ograma. ;iguiente

0b,i etEvos
Despt;: de leer;' cstuCiar cslc ccpt:.;lo, usted tje be r

-,,9$nsfb,$i:i,:modificab'les rplicando :' ,,,no ir rn 9 ifi.g 9., e ! die,1o dql p ro g rama.


", Dfinirrclses.r,eirS'ables basadas

e,

--Ec

ib,i

p t9g

r:

rn

as que. s ea f ci I m e n te'

o Diferenciar
pnotected.

las clases abstractas y la interfaz Java.

b Definir mtodos utilizando el modificadoi


e Analizar cadenas de caracte'res utilizando el
objeto StrinETokenizer.

sn

,:,,h!r:encitfAi,abi-tiactas y mtodo5 .., F:!tltlgs:.;,,..: ,

1-.,.,:;.,'i':.i,:',ill;..,llt1.f::.,'-'";; ;'....:.:::.';.|.'1::..:::.l|.:::i:]].::]:.:.j]:.
r'. '
'-;'-iiLrl.lrlt_:.1i

fi

':i:i.11:..'ri:i,:
.r.

...
.

. :..

::.1-:-: ,;. ' : :'r'.t..i r':tl

,,,i':.,:

,.

713

714

Captuo

13

Herencia y polimorfismo

lntroduccn

ffin este captulo describiremos caractedsticas imp_ortantes y poderos.as

polimorfismo

::ngt:::',#"*adores

cin orienrada a objeros: ra herencia 9e la programa_ p"l1-"rn.*o. n'";;;;r," l | se inrodujo caracierstica herencia de ia programcin "r orientada ra a objetos.-g"r," captulo propor_ cionaremos una expricacin ms=detallada y ejempros de n"r*"iuEl segundo tema ms importanre qu" ." uuo.oia *i" ,"prn iL x erpolbnrfis., que constituye offa caracterstica funamental A" iu "" p.og;;;;;' enviar el mismo *"^"r-J a oo;etos

llffittnH:
6L

Esto ind

Gato
(

cuent.a . calcuLaCuotaMensual

),.

sub<
N

mensaje

polimrfico

fico

oL o$m c'elm* ques' entonces se ejecutar el mtodo calculcuotaMensual "u"ot" d.fi rffi cuentacheques' En consecuencia, enviar el mensaje podra oarporlesnraao helmifo de diferentes mtodos. El mensaje calculacuotaMensuar se denomina la:4&,i
porque dependiendo del objeto receptor, se ejecutan dir,"oo,

donde cuenta puede ser un objeto cuentaAhorro o rm objeto cuenffireqrx" si es un objeto cuentaAhorro, entonces se ejecutar el mtodo carcutaG.otallerrsd do para la clase cuentaAhorro. De semejante,

osn
gbclase superclase

**

explicaremos el polimorfi sm.


I

fismo ayuda a escribir cdigo qu"

",

ficil

de modifrca

-todoo

a pdin-

"ir""L

En este

.--r$

13.1 Un ejemplo simple


Antes de enhar en detalles, empezaremos con un ejemplo sencillo de'herenciaypotimfismo para calentar el ambiente. Empezareos con una clase que modela una .* bancaria' De manera expresa hacemos'que esta cuenta sea bastantl r"r"ilu-ffiffi no se inciuye ningn constructor) p*u Lofo"u*os en el mecanismo de herencia. A con_ tinuacin se presenta la definicin;

ffi'ne

class Mascota{ private String nombre; public Strj_ng obtenNombre( ) { return nombre;
1

public void asignaNombre (String nombre = nornbreMascota; .


1

nombreMascota)

public Sr.ring habla ( ) t return rSoy Lu pequea tierna mascota.r; ]


)
y
a continuacin se presenta un fragmento de cdigo muestra que

utiliza la clase:

Mascota mi_Mascota = new Mascota( ),. System. out.println (miMascota-habIa O);

ilqr#i

t3.l Unelrnfloinpb

7lJ

Hay muchos tipos de mascotas diferentes, de modo que realmente nolodennesperr" que una clse pueda modelarlos a todos. Todo mundo sabe cuntos perros, gabs yrcfohs distintos hay, por ejemplo. Definiremos las clases individuales Gato y perro paramoddrlas de manera ms precisa que la clase genrica Mascota. Luego, envezde definirlas dm nuevas clases independientemente, los definiremos con base en la clase Mascota. Armqrrc son diferentes, comparten la caracterstica comn de ser mascotas, de modo que tiene sentido deducir ambas clases a partir de la clase Mascota. Esto es herencia. Haremos que las clases Perro y Gato hereden los miembros de datos y mtodos de la clase Mascota.

A continuacin veremos cmo es posible definir la clase Gato usando herencia:


Esto indica que Gato es una

subclase de

Mascota

cLass Gato extends Mascota { public Strj-ng habla ( ) { return tNo me des rdenes. \n', + 'Hblo slo cuando quiero. )
I

'r ;

):

La clase Gato se denomina subclase o clase derivada, y la clase Mascota se denomina superclase oclase base.Patadefinirunasubclaseseulizalapalabrareservadaextends. Los miembros de datos y mtodos de una superclase son heredados por sus subclases. As, por ejemplo, el siguiente cdigo es vlido:

Gato miGato = new Gato ( ) ; miGato.asignaNombre (r'Cha Cha',)

System.out.prinlln("HoIa, mi nombre es rt +
miGato,obtenNombre O ) ;
;A:i

En la clase Gato, se observa que el cuerpo del mtodo habla es diferente. Decimos que la clase Gato redefine al mtodo habla. Por ejemplo, el cdigo

cato micato = new Gat.o ( ) ; miGato. asignaNombre ( "Puff Puf f " ),.
System. out. . println (miGato. obtenNombre System. out.print,ln (miGato. habla ( ) ) ;
resulta en

( ) + ,' dice : ,,

);

dice: rdenes. Hablo sIo cuando quiero.


Tambin es posible definir mtodos y miembros de datos apna subclase. La siguiente clade Pe.rro define un mtodo adicional denominado trae:

clasE Perro exterrd Mascota { publie String trae ( ) { return ,'S, amo. Traer."; )
)

:r:-":?]t*9

Y'.'a!+r]]T:,i]:fi Tryfr

ffi

ryqfi r:]]=..*

*ffi

716

Captulo

l3

Herencia y polimorfismo

Adems de utilizar todos los mtodos heredados, es posible llamar al mtodo trae si trata de un peno:

se

System.out.println(miperro.habla( ) ) ; System. out .prj-nt1n (miperro. trae ( ));


ts'lil di^^.

Perro miperro = new perro ( ) miPerro. asignaNombre ( r, Fif i,r ),. System. out . println (miperro . obt.enNombre ( ) + ,, dice
,.

Soy tu peguea tierna mascot.a. S, amo. Traer.

p
COMPROBA

'

Ahora, considere el cdigo siguiente:

Mascota mascotaUno = new perro ( ) Mascota mascotaDos = new Gat.o ( ) ;

rPid
,.

,/

Funciona? La respuesta es s. cuando una variable (como mascotauno) se declara como de clase s (como Mascota),.la variable puede hacei referencia a una instancia de s o a cualquiera de sus subcrases (como eerro y Gato). La inversa no es vlicla; por ejempio,

Perro mi.perro = new Mascota( ); +NOVUDO

El de que la misma variable pueda hacer referencia .hecho a una instancia de una clase diferente da por resultado polimorfismo. Las dos ,lgui"nt", s"ntencias producen el mismo resultado, dependiendo de si p es perro o Gato:

Mascota p,

p = new perro( ),. System.out.println(p.habla ( p = new Gato( ); system.our.println (p.hab1a (


mtodo, ooltmorltco

));
));

El m^todo habla se denomina mtodo polimrfico. Si una variable se declara.de tipo i y s" r"fi"r" a una instancia de una subclase de s, entonces es necesario convertir ta varialle a ra subclase."u;;;; ilamen mtodos,no hereditarios de la subclase. Por ejempto, *too trae se define slo en la clase perro. As, cdigos "i
como

Mascota p,

p = new perro( ),. System. out . println

clases nc relacion

(p

trae

<--

NOVLIDO

X3.2

Definicin de clases con

herencia

Zn7

no son vlidos. Es necesario conveftir p a Perro, como en

lvlascota p;

P = new Perro( ); System.out.println( ((perro)p) .trae{ )

);

Siempre que se requiera ilamar a un mtodo nico de una subclase, es necesario convertir ia variable a la subclase si el tipo declarado de la variable es la superclase. Para utilizar en nuestros programas de manera eficaz herencia y polimorfismo, es necesario dominar muchas reglas asociadas con stos. Tales reglas se presentarn en el resto del captulo.

GOMPROBACN

1. Defina la clase Reptil como una subclase de la clase Mascota.

El mtodo habla de-

rpida v
ra como

vuelve una cadena vaca.


,,

Cul de las siguientes sentencias es vlida?

Mascota m = new Gato0; Gato g = new MascotaO;

ieSoa
,mplo,

3.

Es vlido el cdigo siguiente?

Mascota P = new Perro


de una
rcen el
X

System.out.println(p.trae (

(.) ;

))

3.2 | Definicin de clases con herenca

Suponga que queremos mantener una clase lista para una clase cuya lista de estudiantes incluye tanto estudiantes no graduados como graduados. Para cada estudiante se registra su nombre, las calificaciones en tres exmenes y la calificacin final en el curso. LJcalificacin final en el curso, aprobado o no aprobado, se determina mediante la siguiente

frmula:

Esquerna de puntuacin
No graduado

de 5,
)s

no

Graduado '

Aprobado si (examenl + examen2 + examen3)/3 > = g0

3rro, Qu tipos de objetos deberan utilizase para modelar los estudiantes no graduados

clases no relacinadas

relacionadas si no estn vinculadas por alguna relacin de herencia; es decir, si ninguna de ellas es una clase ancestro o descendiente de otra y tampoco comparten ningn un""r-

y los estudiantes graduados? Bsicamente, hay dos formas para disear estas clases. La primera consiste en definir dos clases no relacionadas: una para los estudiantes no graduados y otra pata los estudiantes graduados. Estas dos clases se denominan clasel no

Captulo

13

Herencia y polimorfismo

!'"

diantes no gradudos. La

graduados como l-u, r"gunda y tercera son Ia ctase EstudianteGra_ duado, para registrar el comportamiento "tur"respcfico de los estudlantes. clase EstudianteNoGraduaao, para r.girtr*it.ornponu-i;;;;;;""urco _graduados, y l de los estudiantes no'graduados.

En realidad, definiremos tres clases. La primera es la clase Estudante, donde se in_ corporarn los datos v comportamiento comunes tanto de los estudiantes

ff [:,:#H::T#ffH-'":"*::i:i::"q]$::'."""'1,i:#i";'"'nandup,icando graduaaos'ililffiiaf|:* ti Jdl;; ;;;; ;;' J" mo do e :,T:::',: :;:#ff n il::l"J #1"nl": ".n
cdigos comunes a ambas clases. Aunque tol estuiantes
qu es r a s do s

tro comn.rLa segunda forma conslste en modeiar los estudiantes no gad.uados estudiantes graduados usando clases que y lq* estn relacionadas mediante una Jerarqua de herencia. Definir dos clases no relacionadls para entidades que comparten.datos o compofta_

publ
non

)
n"ottl.

crasetstudi;te s; define o,no ," *u".r

de ros

esru_

a conrinuacin:

@
l

,'
I I

Desarroll_o de ejemplo del captulo t_3: Estudiante Archivo: EsLudiante. j ava

!.;

/*
class Estudiante { protected final static int NttM DE_EXAMENES =3 protected String nombre; Los campos protegidos son protected int [] examen,. visibles a los objetos protected String calificacioncurso descendientes. i public Estudiante( ) { ths("Sin nofirrrI.

ti

extiende

public Estudiante (String nombreEstudiante) ,


J

calif i-cacionCurso = r ****,

nombre = nombreEstudiante,. examen = new int, INUM_DE_EXAMENES]


,.

public St.ring obtenCali.ficacionCurso ( ) { return ca1 if icacj_onCurso ;

Java' la clase object se convierte de forma automtica en ra supercrase de una clase si sta se define sin la palabra reservada extends' D" ,e.ni"u -un.tu debe decirse que dos clases no estn i.""iru, relacionadas si no comparten ningrin ancestro comn

rEn

aparte de Object.

.*$,*3.
i

I
13.2
Definicin de clases con

herencia 719

publc String obt.enNombre ( ) { return nombre;


)

rl sob
s

public int obtenCalifExamen (int return examen lnumExamen- ]-1,'


)

numExamen)

se in!e dos

como anteGra:.: tdos, y 1:.,

pubLic void asignaNombre (string nuevoNombre) nombre = nuevoNombre;


)

los

estu-

acin:

public void asignaCalifExarnen(int numExamen, int califExamen) { examen lnumExamen-1] = califExamen;


)

W
Observe que el modificador para las variables de instancia es protected, lo cual las hace visibles y accesibles a las instancias de la clase y las clases descendientes. Si declaramos un miembro de datos de una clase private, entonces este miembro de datos slo es accesible a las instancias de la clase, Si un miembro de datos lo declaramos como public, entonces el miembro de datos es accesible para todo el mundo. Se declaran como protected para que sean accesibles slo a las instancias de la clase y a las clases descendientes. M adelante en este captulo analizaremos con ms detalle el modifica-

dor protected.
extiende

Definiremos las clases EstudianteNoGraduado y EstudianteGraduado como subclaLa diferencia entre estas dos clases reside en cmo se calculan las calificaciones finales del curso. A continuacin se presenta la definicin de ambas subclases:
ses de la clase Estudiante. En Java se dice que una.clase exende su superclase.

class EstudianteGraduado extends Estudiante { public void calculaCalif icacionCurso


O

int toEal = 0; for (lnt i = 0; i < NUM DE-EXAMENES; i++) i total += examen[il;
)

if

(Lora1/NLM_DE_EXAMENES >=

calif icacionCurso = ) else { calif icacioncurso =


:fine sin laciona)

80) t
,'

"Aprobadorr

rrNo Aprobado'r;

*qry!*

rsdua9rlLurso

int, total = 0; for (int 1 i = 0,' i < NUM_DE_EXAMENES; i++) total + examen Ii] ] if (total/NuM_DE_E)LAIvTENES >= 76 { calif icacioncurso =,[p9[6!srr,. else ] { calif icacioncurso = ,,No Aprobad.o'
,.

(, t

]
En la figura 13'1 s.e muesffa ei diagrama de clases que relaciona estas tres clases. observe el uso del smbolo (#) para er modificador protected. tamuin observe :; las subclases no se muestran los miembros de datos ni los mtodcs heredados. cuando se observa una flecha de herencia que conecta una subcrase con su supercrase, se sabe que los miembros de datos y ros mtodos en ra supercrase tambin son'apricabi; ;#: clases' Se asignan mtodos y miembros de datos a las subclases slo si se definen en las subclases o se redefin91 e1 las subciases (discutiremos la redefinicin en .t^il.^,na, aa,etltg captulo). En ra figura 13.1, ambas subclases tienen asociado ei mtodo :.l."rt: calculacalificacioncurso porque ste est definido en las subclases.

+ NUM_DE_EXAMENES
F nombre

,,-

# examen ,... ,.,.:, # calificacionCrs

El smbolo # indica ios miembros protegidos

+Estudiante():void
+ Estr,rdiante(String) : void + obtenCaficacionCurso( ) : String + obtenNombre( ) : String + obtenCalificacionExamen(int) : int + asignaNombre(String) : void + asignaCalificacionExamen(inr, int) : void

+ obtenCalificacionCurso(

) : String

+ obtenCalificacionCurso( ) : String

igura 13.1 una

superclase Estudiante y sus subclases EstudianteGraduado y EstudianteNoGraduado.

Figura

13.3

Cmo utilizar clases en oi-ma eficaz utilizando polimorfismo

?41

I. COMPROBAC!N
'7 rGptaa /

cu1 es Ia subclase y cul la superclase en la siguiente declaracin?

class X extends y {.
7

.}

Qu modificador de visibilidad permite que 1os miembros de datos de una super_ clase sean accesibles a las instancias de ias subclases?

13.3 I Cmo utilizar clases en fornna efieaz utilizando polinnonfismo


Ahora veremos cmo se pueden usar de manera eftcazlaclase Estudiante y sus subclases en el programa de la lista de una clase. Puesto que ambos tipo de estudiante se matriculan en la misma clase, es necesario declarar los dos siguienies arreglos para mantener la lista de la clase?

es ciases. i/e que en luando se


sabe que r las sub_ en en las

EstudianteGraduado listaGraduados[20j;
EstudianteNoGraduado listaNoGraduados [20]
;

aile ms
mtodo

Fn el captulo 10 mencionamos que un arreglo debe contener elemenros del mismo tipo de datos. Por ejemplo, no es posible almacenar enteros y nmeros reales en el miso
vlida cuando los elementos del aneglo son objetos. Basta declarar un nico anglo; por ejemplo,

los estudiantes graduados y oro para los no graduados. Esta regla, sin embargo,

arreglo. Para acatar esta regla, parece necesario deciarar dos arregios d.iferentes: uno para

nt es

Estudiante Iista[40];
Los elementos del arreglo lista pueden ser instancias de ia clase Estudiante o de sus descendientes las clases EstudianteGraduado y EstudianteNoGraduado. En la figura i3.2 se ilustra el arreglo con ambos tipos de estudiantes como elementos del arreglol

lista

Figura 13"2

El arreglo lista con elementos que se refieren a instancias de las clases Est.diarteGraduado o EstudianteNoGraduado.

722 Captulo't3

Herencia y polimorfismo

Antes de mostrar cmo se Lltiliza este areglo en er programa, expric.aremos el con_ cepto de polimorfismo. En su forma ms simple, el polimoifisn o ,..uprr., a,una nica variable que se refiere a objetos de diferentes .toi.r.'co"'"i., p"r eJemplo, la declara_

Est.udiante estudiante,.
Con esta declaracin, no sio se puede decir:

est.udi_ante = new Est.udiant.e( ),.


sino tambin

estudi-ante = new Est.udiantecraduado( );


o bin,

estudiante =

nertr EstudianteNoGrad.uado(

);

En otras palabras, la variable_ simple estudiante no est limitada a objetos de la clase Estudiante, sino que puede referirse cualquier objeto e las clases que descienden de Estudiante. De manera semejante, es posibl hacer lgo to ,igui"nt",

"o*o

lista lista l-ista lista

[0] [1] [2] [3]

= ( ); = new Estudiant.eNoGraduado ( ) ; = nes EstudianteNoGraduado ( ) ; = ner EstudianteGraduado ( )


new Estudiant.eGraduado
,.

lases

una variable de la clase X se refiera a un objeto hermanas de la superclas o de clases hermanas de X. Las clases hermanasson aquellas que comparten un ancestro comn' Por ejempio, las siguientes sentencias no son vlidas:

Sin embargo, no se puede hacer que

EstudianteGraduado estL, est2

,.

ruOVt_lOO_____-

I est.2

estl = new Estudiante O ; = nev EstudianteNoGraduado

,.

Luego, para calcular la calificacin del curso utilizando el arreglo lista se ejecuta:

Eor (int, i = O; i < contadorEstudiantes,. i++) t lista Ii] .. calculaCalif icacionCurso O


,.

mtodo calcuracarificacioncurso se denomina potimrficoporqu"

si lista[i] se refiere a un EstudianteGraduado, entonces se ejecuta el mtodo calculacalificacioncurso de la clase EstudianteGraduado, y si se refiere a un EstudianteNoGraduado' se ejecuta el mtodo calculacalificacioncurso de la clase EstudianteNoGraduado.
,,"fiere a mtodos

El

de

'13"3

Cmo utilizar clases en forma eficaz utilizando polimorfismo

v?"3

Ciierentes ciases, ciependrendo de si el objeto al qlle hace refencia listalil. El polimorfismo permite mantener 1a lista de clase con un aregio en vez de mantener un arreglo por sepaiado para cada tipo de estudiante, con 1o cual el procesaniento se simplifica enormemente.
.beneficios del

,:lrolimorfismo

Ei pomorfismo hace posible extender y modificar un programa de manera continua y fci1. Suponga, por ejemplo, qrie es necesario aadir un tercer tipo de estudiante; a saber, un estudiante invitado, al programa de la lista de clase. Si se tiene que definir un arreglo diferente para cada tipo de estudiante, esta extensin obiiga a definir una nueva ciase y un tercer an"eglo para estudiantes invitados. Pero con polimorfismo, slo es necesario definir una nueva subclase de Estudiante. Y en la medida en que esta nueva subclase incluye el mtodo calculaCalificacionCurso correcto, el ciclo for para calcular Ia calificacin del curso de los estudi.antes sigue siendo el mismo. Sin polimorfismo, no slo necesitamos aadir el nuevo cdigo, sino que tambin debemos reescribir el cdigo existente para dar cabida a los cambios. Con polimorfismo, por otra parte, no necesitamos modificar el cdigo existente. La modificacin del cdigo existente es tediosa y muy propensa a errores. Un ligero cambio en un cdigo existente podra ocasionar que el programa dejase de funcionar cofrectamente. Para tener la cetteza de que un cambio en una porcin de un cdigo existente no afecta otras porciones del cdigo existente en forma adversa, es necesario comprender muy bien el cdigo existente. Adems, la comprensin del cdigo, especialmente si es largo y/o realizado por otras personas, es una tarea que consume mucho tiempo. Un elemento del aneglo lista es una referencia a una instancia de la clase EstudianteGraduado o de la clase EstudianteNoGraduado. La mayor parte de las veces, no necesitamos saber de qu tipo es. Sin embargo, hay veces en que necesitamos conocer la clase del objeto al que se hace referencia. Por ejemplo, podemos querer buscar el nmero de estudiantes no graduados que han aprobado el curso. Para determinar la clase de un objeto, usamos el operador instanceof. Este operador se utiliza como se muestra a continuacin:

; de

la ciase lcienden de

l un objeto l qlte comAS:

Estudiante x = new EstudianteNoGraduado( );

if ( x instanceof EstudianteNoGraduado ) { System.out..print.ln("Sr. X es un estudiante no graduadorr); ) etse { Systrem.out.println("Sr. X es un estudiante graduad.o',) ;


) Lo anterior imprime Mr. X es un estudiante no graduado. El siguiente cdigo contabiliza
el nmero de estudiantes no graduados que hay en el arreglo lista.

eJecuta;

int contadorNoGraduados = 0; for (int i" = O; i < numeroDeEstudiantes; i++) t if ( lista Ii] instanceof Estudiant.elloCrad.uado ) {
a

lculaCa li-

conLadorNoGraduados++,.

JoGradua-

\
J

duado. El
Ltodos de

724

Captu[o

13

Herencia y polimorfismo

1. Suponga que Camion y Motocicleta son subclases de Vehiculo.


COMFROBACIN

guientes declaraciones son incorrectas

Cules de las si.

"rdpida /

rl

Camion Vehiculo

c = new Vehiculo( ); - ); v = new Camion( Mot.obicleta m1 = new Vehi-culo ( ) ; Mot-ocicleta 12 = new Camion( );

2.

CuI es el propsito del operador instanceof?

En esta seccin y en las secciones 13.5 y 13.6 describiremos las reglas de herencia. En esta seccin explicaremos qu miembros (variables y mtodos) de una superclase se heredan en una subclase y cmo se accede a estos miembros. Adems de declarar miembros public y private, podemos declararlos como protected. El modificador protected es til slo si se usa con herencia. Considere las siguientes declaraciones:
suDer es una class super t 'G reservada: no la use. int campo_public_Super; ,public proLected nt campo_protected_Super; private int campo_private_Super; public Super0 { campo_public_Super = l-0; campo_prot.ected_Super = 20 campo_private_Super = 30; palabra

13.4 | Herencia y accesblidad de miembros

)
I

class Sub exlends Super { public int campo3ublic_Sub; protected int. campojrotected_Sub; private int campo_private_Sub; public Sub O { campo_pub1ic._Sub = 100, campo_protecLed_Sub = 200; . campo3rivate_Sub = 300 i
)

)
Para ilustrarlo usamos variables de instancia, aunque las reglas que se describen aqu son igualmente vlidas para otros tipos de miembros (variables de clase, mtodos de clase y mtodos de instancia). Para los tres modificadores usamos la representacin grfica que se muestra en la figura 13.3.

XN,

'

3.4

Herencia y accesibilidad de

miembros VZs

:Sub

EstO muestra

que los componentes

heredados de la superclase forman parte de Ia instancia de la subclase.

encia. En
tse Se he_

riembros rd es til
Jerarqua tle clase

r-:r..]

ffil
Fig*ona

Instancias

?3'3

Esta representacin es slo para efectos de

Representacin grfica de superclases y subclases con miembros pub!i<, private y prote(ted. (Nofd: ilustracin y no es un diagrama UwIL formal.)

Usted ya conoce la diferencia entre los modificadores public y private. {"In miembro pblico (public) es accesible para cualquier mtodo, pero un miemtro privado (private) slo es accesible a los mtodos que pertenecen a li misma clase. A continuicin se

ilustrar esta cuestin. Considere una clase que no est relacionada con las clases super

y Sub:

class Cliente { public void prueba O { Super miSuper = new Super O ; Sub miSub = new Sub O ; int j. = miSuper. campo_public_Super,. int j = miSub.campo_public_Super; ,//hered.ado por vuoo _-> int, k = miSub.campo_public_Super;
)

miSub

son que

Los miembros pblicos de una clase, sean heredados o no, son accesibies desde cualquier objeto o clase. Los miembros privados de una clase, por otra parte, nunca son accesibles desde fuera del objeto o clase. En consecuencia, todlas las siguientes sentencias, si se sitan en el mtodo prueba de la clase criente, no son vlidas:

Ney

vovlloo----->

int 1 = misuper.campo3rivat.e_Super; int m = miSub.campo_prj_vat.e_Sub; int n = miSub.campo_pri-vate_Super,.

lf
V26
Captulo

..*
l3
Herencia y polimorfismo

Acces i bii id;.1 *es1r


'i:l :"riociq

{l ienie"

:Cliente
:Sub :SuDer

?r- -_-l/
Slo los miembros embros pblicos, los definidos os para la clase y los heredados, ados, son sc visibles desde fr-reia.Todo a.Todo Ilo dems est oultor desde fuera.
1

\, \

\t--.
,.: J

-]./

: l-lx:],'.
Slo los miembros pblicos son visibles

X:l:'

Figura 1 3.4 oiferencia entre los modificadores publc, private y protected.


desde fuera.

Un miembro protegido (protected) es accesible slo a los mtodos que pertenecen a la misma clase o a las clases descendientes. Es inaccesible a los mtodoJde una clase no relacionada. Todas las siguientes sentencias, si se colocan en el mtodo prueba de la clase Cliente, no son vlidas:

int o = misuper.campo_protect.ed Super;

X ruovl-loo->

int p = misub.campo protected. int q = miSub.campo_prot.ected

Sub; Super,.

En la figura 13.4 se resume la accesibilidad de los miembros de una clase desde un mtodo de una clase no relacionada. A continuacin estudiaremos la accesibilidad de los miembros de una clase desde los mtodos de un objeto Sub. Un mtodo en el objeto Sub puede acceder tanto a los miembros protegidos como a los miembros pblicos de Super, pero no a los miembros privados de Super. En la figura 13.5 se resume la accesibilidad de los miembros de un mtodo de un objeto Sub. La figura 13.5 muestra el caso en el que un mtodo de un objeto Sub est accediendo a sus propios miembros. Todo, salvo los miembros privados de ia clase Super, es accesible desde un mtodo de la clase Sub. Qu ocurre cuando se accede a ios miembros de un objeto desde otro objeto que pertenece a la misma ciase? Si un miembro X, ya sea heredado o definido onu Llur., accesible desde una instancia de la clase, entonces X tambin es accesible "n "t desde todas 1as instancias de la misma clase. La figura 13.6 ilustra que una instancia puede acceder a los mtodos de otras instancias de la misma clase.

'3.4
Aercsihiiidai iescie un
niri. tie

Herencia y accesibilidatJ de

miembros

VAV

:Sub

ia lir:lc'5ub"
LI

i-i I it
todo
Desde un mtodo de Sub es visible, excePto los miembros Privados de su superclase.

il

.:1

I L-=-

Figura 13.5

y protected' Todo, excepto los miembros de tiPo Diferencia entre los modificadores public, Brivate la clase Sub' private de la clase Super, es visible desde un mtodo de

visibles

Si un miembro de dtos es

accesible desde unalnstancia, ese miembro de datos tambin es accesible desde otralnstancia

ste podra ser Privado,

protegido o Pblico.

necen a

lase no

adela

FiEuera '13.6

ffice5blesdesdeunainstanciatambinsonaccesiblesde5deotrasinstanciasde
la misma clase.

Considere las dos clases siguientes:

class SuPer

public void superASuper( Super otrosuper){


sde un
VLIDO

;de los

-.>

int i = otrosuper.campo-public-Super; int j = otrosuper.campo-protected-Super; int 1 = oLrosuper.campo-private-Super;

niemivados

i
)

do

de

iendo
scesi-

class Sub extends public void /


vLlDo ------>

Super

l
as

que las

subASub

( Sub

otsrosub) {

se, es a los

int i = ot.roSub.camPo-Public-Sub; int j = otroSub.campo-proLected-Sub; int k = otroSub.campo-private-Sub;

Captulo

13

Herencia y polimorfismo

| int I = otrosub. campo-public-super; //miembros I it t * = ot.roSub.campo-protecLed-Super;//heredados X ruOVt"loO--------> int n = otrosub.campo-private-Super; /


v_loo
_______+

rap

]
Todas las sentencias en los dos mtodos, excepto la ltima en subASub, son vlidas porque los miembros accesibles a un objeto tambin son accesibles desde otros objetos de la misma clase. Ahora, considere las dos clases siguientes:

class SuPer { public void. suPerASub (Sub sub) { int i = sub.campo-public-Sub,' / VEI-IOO sub . campo_protected_Sub I nt
vsub . campo_privat.e_Sub
;

X ruovLtoo- I io,
] ] class

Sub extends SuPer {

public / VitttoO-------) int int X ruovr-roo-----> int


)

void subASuper(Super miSuper) { i = misuper.campo-publj-c-Super; j = misuper.campo-protecLed-Super; k = mSuper. campo_privat.e-Super;


Ei comPilad'

)
Los dos mtodos muestran que slo los rniembros pblicos de un objeto son accesibles desde otro objeto si los dos objetos perteneeen a diferetes clases. Si una clase es una subclase de la otra carece de importancia aqu.

autom

Adems de los modificadores publc, prvate y protected, Java soporta un cuarto mdificador de visibilidad denominado visibifidad del paquete. Si en la declaracin no se incluye ningn modificador explcito (publi<, private y protected) etonces el componente ei visible para el paquete, lo cual significa que el componente es visibie desde cuajquer mtodo de una clase que pertenezca al mismo paquete:que,l clase del componente.'La visibilidad det paQuete no es tan lgrtic com la de,loS tios tres modificadores de visibilidad y, por ello, no se ana,
liza en eltexto,

13.5

Herencia y

constructores ZZg

f t.

,''oMPRoBAchi

Si X es un miembro p.iuaOo " de 5uper?

lu.tu."

super, es X

u...ribl" desde

una subclase

raotaa -./

a L.

Si X es un miembro protegido de la clase Super, es X de una instancia accesible desde otra instancia de Super? eu ocurre con ls instancias de una subclase de 5uper?

vlidas,.

objetos

13.5 i F{erencia yconstructores


miembros de una ,up"r"lur", ios constructores de una superclase no son heredados por sus subclases. Esto significa que es necesario definir un constructor para una clase o utilizar el constructor predlterminado aadido por el lador' Como se mencion en el captulo 4, un constructor predeterminado "o-fise aade a una clase si no se declara ninguno pari ia clase. una definicin de clase como herencia'
F'n esta seccin explicaremos cmo los consuctores de una clase se ven afectados por la

A diferencia de otros

class persona { public void decirHola{


System.
)

out.princln ( "Bien, ho1a.,, ),.

]
es equivalente a

class Persona { public persona( ) {


El

compilador lo aade automticamente


a la clase.

suPer ( )

; <.-

Esta sentencia llama al

constructor de la superclase.

ar-

public void decirHola ( ) { System. out . pri-ntln ( rBien, ho1a. ]


)
La sentencia

,,)

fil.
ld)
'nts-..

tn
a-

super( );
llama al co'nstructor de la superclase. Cada clase tiene una superclase. Si la declaracin de la clase no designa de forma explcita la superclase con la lusula extends, entonces la superclase de la clase es ia clasJobject.

730

Captulo

13

Herencia y polimorismo

Si declara'un constructor, entonces no se aade ningn constructor 1 -""'c ..^_ --^ forma Predeterminada a la clase. Por ejemplo, si define una clase

"orno,

class MiClase { public MlClase (int x) {

i
\ t
entonces una sentencia como

MiClase prueba = new MiClase ( ) ;


no es vlida porque Miclase no tiene ningn constructor que coincida con el anterior. sl el constructor definido no contiene una llamada explcita al constructor de la perclase, entonces el compilador aade la sentencia:

su_

super ( )

,.

como la primera sentencia del constructor. Por ejemplo, si el constructor se define como

class MiClase { private int milnt; public lrtiClase O t milnt = 10;


)
)
entonces el compilador reescribir el constructor como

i;
:

:-,::=:

public lliCtase( ) { super( ) ;'. milnt = 10;


A continuacin
se ver otro ejemplo. Considere las siguientes definiciones de clase:
Es neces lla

class Vehiculo { private String niv; public VehcuLo (String numeroldVehiculo) { niv = numerofdvehiculo;
)

contrario
aadi pro'

debido

ac

con el

t*,,,1#j.

13.5

Herencia y constructores

73'

public String obtenerNlVO { reiurn niv;

)
Puesto que la clase tiene un constructor, a aquella no se aade ningn constructor predeterminado. Esto significa que una sentencia como:

Vehicu]o miCoche = new VehiculoO;


provocar un elror de compilacin porque la clase no tiene un constructor que coincida
con la llamada anterior. Esto es realmente 1o que queremos porque no deseamos crear una

nterior

::
.,i:

rdela

su
::
-

instancia de Vehiculo sin un nmero de identificacin del vehulo. A continuacin consideraremos una definicin de subclase para camiones. Un objeto Camion tiene una variable de instancia adicional denominada cargaMaxima que se refiere al peso de la carga mxima que puede transportar el camin. Se supone que la carga mxima puede varir (por ejemplo, dependiendo de cunto paga de tarifa e1 dueo del carrn). A ontinuacin se presenta el primer intento:

class

Camon extends

Vehiculo {
nuevaCarga) {

Si compilamos esta definicin, obtenemos un effor del compilador. Debido a que para la ciase no se ha definido ningn constructor, el compilador aade un constructoien forma predeterminada.

public void Camion( ) {


]
super ( ) ;

Este cOnstructor llama al cons*uctor de la supercLase sin argumentos, pero no existe ninguna coincidencia con el constructor en la sperclase. As, iesulta un error de compilacin. A continuacin se presenta una definicin correcta:
,

Es necesario hacer esta

llamada; en caso

contrariq el compilador aadir superfl, que


debido
provocar un error a que no coincide con el constructor de

class Camion extends Vehiculo { private int cargaMaxima,. public Camion(nt pesoMaximo, String niv) { ::_-.-._-> super(niv); cargaMaxim = pesoMaximo; public void establecerCargaMaxima(int nuevaCarga) {
)

Vehiculo.

#.*r

t5

Captulo

'[

Herencia y polimorfismo

cargaMaxima = nuevaCarga;

publc int esLablecerCargaMaxima return cargaMaxima;

O{

EstudianteNoA continuacin, este conocimiento se aplicar al diseo de las clases el nombre, enque acepte constructor un queremos Si Graduado y EstudianteGraduado.

ya que el constructor definido tonces es nlcesario definir un constmctor en ambas clases, que podemos cfear instancias observe clases. estas lo heredan no en la clase Estudiante continuacin: a muestra se de estas clases como

::::

lr.'j ill,
1

estudiantelestudiante2

= new EstudianteNoGraduado O ; ( = new EstudianteGraduado ) ;

y no porque el defidebido a que el constructor predeterminado lo aade el compilador, constructores de que los nido en la clase Estudiante io hereden las subclases. Recuerde una superclase no 1os heredan sus subclases' recordarse para el A continuacin se presentan una regla y una directriz que deben
constructor de una subclase:

i'i;;i
j-ii'.

ll:,,

rti,i

clase abstr

)l

Siempreproporcioneunconstructorparucodaclasequedefina.Nodependade
io

La

i c o n ii ry ct or s P,r ed9t3 r m i n a d,o s,

abst
una

i':i,,''if*:l!1R

1. Cmo se llama al constructor de la superclase desde su subclase? 2. Qu sentencia debe aadirse al constructor de una subclase si el programador
incluye en forma exPlcita uno?

no

de la 3. Modifique la definicin de EstudianteGraduado y EstudianteNoGraduado


muestra a conseccin 13.1 de modo que sea posible crear sus instancias como se tinuacin:

Li

etudiantel estudiante2 estudiante3 estudiante4

=
=
=

new EstudianEeNoGraduado

;
;

new EstudianteNoGraduado("Mr' Espresso'r) new EstudianteGraduado O ; new EstudianteGraduado(I'Ms. Latte") ;

I
1

3,6

Superclases abstracias y mtodos abstractos

733

d,"_"
)inbre, en_
rr

definido

insrancias

e el defi_ croes de e para el

Cuando definimos una superclase, a menudo necesitamos crear instancias de 1a rnisma. En la seccin 13.5 definimos 1a superclase Estudiante y sus dos subclases, EstudianteGraduado y EstudianteNoGraduado. Se proporcionaron ejemplos de creacin de instancias de ambas clases, pero no se crearon instancias de Estudiante. Tiene sentido crear una instancia de 1a clase Estudiante? Dependiendo de si necesitamos o no crear instancias de Estudiante, debemos definir la clase de manera diferente. En esta seccin describiremos formas distintas para def,nir una superclase. Aun cuando podamos_crear una instancia de Estudiante si as 1o deseamos (debido a la forma en que se ha definido actualmente la clase), existe la necesidad de crear una instancia de Estudiante? Si un estudiante slo puede ser graduado o no graduado, entonces no es necesario crear una instancia de Estudiante. De hecho, debido a la forma en que se ha definido la clase, si se hubiera creado una instancia de Estudiante y se hubiera almacenado en el arreglo lista, el programa habra fallado. Por qu? Porque la clase Estudiante carece de un mtodo calculaCalificacionCurso' A continuacin consideraremos dos casos. En el primero, se supone que un egtudiante debe ser un estudiante graduado o un estudiante no graduado. En el segundo caso, se supone que un estudiante no tiene que ser un estudiante graduado o un estudiante no grduaOo (por ejemplo, el estudiante puede ser un estudiante invitado no matriculado).

3.6 | Supcrelases ahstr@tas y nmtodos ahstraetos

easo

,E:

Ef,

estudiante debe ser graduado o no graduado

En el caso en que un estudiante deba ser un estudiante graduado o uno no graduado, slo

clase abstrcta

-.

necesitamos instancias de EstudianteGraduado y EstudianteNoGraduado. Por tanto, necesitamos definir la clase Estudiante de forma que no'sea posible crear instancias de ella. Una forma consiste en definir Estudiante como una clase abstracta.Una clase abstracta es una clase definida con el modificador abstracto, y de una clase abstracta no es posible crear instancias. A continuacin veremos la manera de definir la clase abstracta Estudiante.

La palabra clave

abstract denota aqu


una clase abstracta.

abstract class :siuciiante { proLected final static int

NUM-DE-EXAIvIENES =

:::-

ri :\:

protected String nombre protected int Il examen; protected String cal j-f icacionCurso public Estudiante O
t

lor no

this(ItSin nombre"),'
i

de Ia
con-

public EsLudiante(String nombreEstudiante)


nombre
La palabra clave

abstract denota aqu

= nombreEstudiante; examen = nel- int INM-DE-ExAMENES] , calificacioncurso - ****rr'

El mtodo abstracto no tiene cuerpo de

1:t:9.:1"ttbu

tnt[to*ttt-'"

::l::"t"'

]o"rr"". pubr-ic void calcuraCalif icacioncurso o, *--i

734

Captuto

l3

Herencia y polimorfismo

public String cal_culaCalificacionCurso O { return calificacionCurso. public String obtenNombre O { return nombre,.
)

---'

public int obLenCalificacionExamen(int numeroExamen) return examen lnumeroExamen_1] t

])

,.

public void estableceNombre (String nombre = nombreNuevo;

nombreNuevo) {

publc void est.ableceCalificacionExamen (int

numeroExamen,

,)
)
mtodo abstracto

examen [numeroExamen-1]

= califica"r:::":::lficacioncurso)

implementacin
de un mtodo

un mtodo abstracto esn mtodo con la palabra crave abstracto, y termina con punto coma, en vez de con un cuerpo de mtodo. unu ;, ,b;;;;;;;si Ia crase conriene ur mtodo abstracto o noptopo..ionu unui.llemenracin se dice que un mtodo esiimpremriri"^riti."n",1., " *.1o abstracto heredal " .ii,o". no tiene mtodos absrractos y-no posee "u.rpo rr*"^0", si una suclas, mJtodos uurtru"i, sin implementa (y no puede incluir la palabra su definicion e cl.sel entonces la subcla se ya no es abstracta, por.lo que y" p"ri1" crear sus instancias. una clase absracta "e tn"ruitliffiru.tuu" "r uortr..t su definicin. observr que la clase abstracta Estudiante tr.n. ,lnu "nri.iJ".-.'"f,ia"euio "n a que ra crase incluye el mtodo abstracto calculacalificacioncurso que no tiene un cuerpo de El objetivo es permitir a sus subclase. mtodo. lu" fioporcionen ra imprementacin der mtodo calculaCalificacionCurso. Si una subclas no r

.i*

cla"JJ;;;n

superclase abstracta
..-

i;::rt;;:i:"cu.ando
La clase

s r a s ubcr as e 1p' c1a' " no es posibre crear instancias de la subclase. "jT se ffata de una,;;;;"", a

y{ n"*i uiol "".".

;."i i::

li :ff '#t i:,::ii:r H H #:::x: D";;;;;un abstracta sio


"rur" menudo se utiliza la expresin super-

.Cn3ejos,,

pistasy,' obstcloi

no crear nstancias de ra ctase. sn ", emb;r;;, una nsrancia no necesariamente implica que la clase sea abstracta. El objetivo de una clase abstracta es defnir aspectos comunes de todas ,u, iuo.tur"s y dejar que argunas porciones, es decir' mtodos abstractos, se.an comptetauos por las suLctases iniuu"ler. La clase Math se clasfica como una crase no i^ri*.iuor., ,n. .rur" fjr.l.".r.r no es posibre crear ninguna instancia. observe que por efncion ,nu .iu!" .ur*.,u es una clase no nstanciabre, aunque Ja inversa no es cierta. Hay ctaies no instanciabres, por ejemplo, la clase Math, que no son uolru.aur. si queremos Jrni, una clase no ;; ; I l, n u,.s,," ; itr l,?l f;

Math, es una crase abstracta? Es cierto que no es posibre crear instancias de Math' pero no es una .r;;;;;;;i. r, ,n, .rur" urriicra, entonces se pueden
ta ctase

";;;;";

!,"*r"

"',?

;?H :T j:j:il: :,: :;

i*"":',,,.i

";;

"

;,;, ;

3,6

Superclases abstractas y mtodos

abstractos
1a

735

En un diagrama de objetos, una clase abstracta se representa utilizando clave abstract. La superclase abstracla Estudiante se lepresenta como
Estudiante
{

palabla

abstracta }

rso) i

caso 2: El estudlante no tie'e por qu 5er graduado o E'o graduado Para el segundo caso, en el que el estudiante no tiene por qu ser graduado o no graduado, podemos disear las clases de dos formas. El primer enfoque consiste en hacer instanciable la clase Estudiante. El segundo enfoque consiste en dejar la clase abstracta

punio y tiene un
:redado. ubclase )mentar

Estudiante y aadir una tercera subclase; por ejemplo, OtroEstudiante, pafa tratar con los estudiantes que no son graduados ni no graduados. Los estudiantes que no son graduados ni no graduados los denominaremos estudiantes no matrculados. Supondremos que estos estudiantes aprobarn el curso si su puntaje medio en el examen es mayor que o igual a 50. Con el primer enfoque, la clase Estudiante se define como se muestra a continua-

cin:
Ya no es una clase

subcla)bserve a clase rtodo. ntodo

------>

abstracta

rtodo lcuena slo


'wper-

class Estudiante { protected fna1 static int NUIVI_DE_EXAMENES = nombre; protected String examen; protected j-nt il calificacionCurso; protected String public Estudiante( ) { this(rtSin nombre");
)

public EsLudiante(Strj-ng nombreEstudianLe) i


nombre examen
ca1 i f

de
alo

nombreEstudiante ; new int INUM*DE_EXAIVIENES]

icacioncurso

to
ta
3S Ya no es un

)
mtodo abstracto

;e
le

e
5,

public void calculaCalificacionCurso( ) { int t.otal- = 0; for (int = O, i < NUM_DE-EXAMENES; i++) total += examen[1];
)

if

(total/NUM_DE-EXAI',IENES >= 50) { calif icacioncurso = t'Aprobado"; ) else {

736

Captuo f

Herencia y polimorfismo

calificacioncurso =

'No Aprobado";

] public String obtenCalificacionCurso( ) { return calif icaconcurso ; ] public String obtenNombre O i rturn nombre;

i
public int obtenCalificacionExamen(int return examen lnumeroExamen- 1] ;
)
numeroExamen)

public void estableceNombre (string nuevoNombre) nombre = nuevoNoilre; ] public void e s t ab1 ec eCal i f icac ionExam':jli:
examen lnumeroExamen-]-l

r:::illllllll;

= cal-ificacionExamen''

)
Estudiante pala lepresentar La clase ya no es abstracta, y podemos clear una instancia de a los estudiantes no matriculados con el segundo enfoque, la clase Estudiante 1a dejamos como abstracta. Para reprea los eitudiantes no matriculados, definimos una tercera subclase denominada

sentaf OtroEstudiante como se muestra a continuacin:

ffi ffi

class OtroEstudiante extends Estudiante { public void calculaCalificacionCurso O { int total = 0; for (in! i = 0; i < NUM-DE-EXAMENES,' i++) { toLal += examen[i];
)

if

(tota1/NLtvl-DE-EXAMENsg

= 50) {
COMPS

calificaconcurso = "Aprobado" ; ] else { calificacionCurso = "No Aprobadorr ; )

La figura 13.7 es un diagrama del programa que incluy-e la tercera-subclase. Todo depende de cadasituaiCul enfoque es m;jor? No existe una rspuesta fcil. situacin dada, podemos para una mejof es el enfoque cul cin]A fin de determinar Considere, por y extensiones. las rnodificaciones lai facilita pieguntarnos qu enfoque

n3"6
Estudiante
{

Superclases abstracias y mtodos

abstracr.cs 7=7

abstract

OtroEstudidnt

'tej

ren). {

Figuna '! 3.7

Diagrama del programa de la superclase abstracta Estrdiante y sus tres subclases.

esentar

repreninada
.

ejemplo, qu enfoque facilita 1a modificacin si se tiene que aadir un nuevo tipo de estudiante, por ejemplo, estudiantes becarios. O bien, consiere el caso en que se modifica 1a regla de asignacin de calificaciones a los estudiantes no graduados y u lo, estudiantes graduados; por ejemplo, una regla donde los criterios de aprobacin son los mismos. Finalmente, no todos los mtodos se pueden declarar omo abstractos.

Los

siguientes tipos de mtodos no se pueden declarar como absactos:

. Mtodos . Mtodos

privados

estticos i:, jr'

,.,
,:

wiffi**x,rytr,$&kffiK**!:51#j!i!its*$i,
COMPROBACN

l,$ ,

txr.ini;iri::i*

1. Puede crear una instancia de una clase abstracta?

rapma

/rt

,/
ua10s

Una clase abstracta, debe incluir un mtodo abstracto?

3. Qu es erneo en la siguiente declaracin?

class Vehiculo { abstract, pubtic obtenNIvO ;

)or

13.7 J FNerencia contra interfaz


La interfaz y la herencia en Java son caractersticas de orientado a objetos. son semejanr., po.q"",u.qu.-.: lenguaje para sop-ortar moderado utiriz'anffi modelar. una reracin ES-UN. Considere, por ejempio, fu, iffintes definiciones de clase:

class Dj.rectorioVerl implements Directorio {

]
class CuentaAhorro extends Cuenta {

i
Deoimos "Directorioverl es un Directorio,, ..cuentaAhorro y es una cuenta,,. Debido esta semejanza' los a Programadores principiantes tienen oificultades en distinguirlas cla_ ramente. Aunque se parece-n, sus prpsits son bastante comportamiento comn (definido por mtodos abstractos) sus e clases no ,"1;.i"";;;;. y una crase puede implementar mltiples interfaces. pi ."*pr", puede "i*irr. ,* clase nica persona que implemente mrtiples interfaces, .o-Lonorctor, viajero y cicrista. Por orra parte, la heencia.se uru p*u compartir caigo Jo;n (incluyendo tanto miembros de datos como mtodos ent ias instancias de cises relacionadas. por eiemplo' las clases EstudianteGraduado y EstudianteNoGraduado son subclases de la lase Estudiante' las clases Camion y tuotciclei" son subclases de la clase vehiculo, etc. Las superclases incluyen miembroi de datos yro metooos que son compartidos por ras subcra_ ses' La relacin ES-LrN que existe na suclur" y .u ,;p.;;il; es una especializa_ cin' de la misma manera en que camion "nt " es un Vehiculo especializado. Esta relacin especializacin no existe de
con

La intertaz Java se

.utilizap*u .pu.tir entre ras instancial

diferen;.

reutilzacn

cdigo por
composicir

li

interfaz Java.

lala pora compartir cdigo comn.

'-::i:::::'tu:

to."I

s9mnartir comportamiento comn. tlse ta.herencia

13.8

Si una entidad A es una

forma especializada de otra entidad B, entonces mod_ Ielas usando herencia. Declare A co.i ruOrtore de B.

iio

. :-i

3.8

Ejemplo de

desarrollo

7Sg

Debemos tener cuidado en no rnezclar el uso cle ia clase de servicio y

1a

principiantes a menudo cometen este elror. Suponga que quiere definir una clase ciue rnantenga una iista de CD de msica. Cu1 cie las dos siguientes definiciones constituye
un mejor diseo?

herencia. i-os

class CDManager extends java.uLit.Arraylist


) cl-,ass CDManager {

private List lista; ]


La primera versin utiliza herencia y define una subciase de Arraylist. La segunda versin define un miembro de datos del tipo ArrayList. La primera versin es un uso indebido de la herencia. Cuando se define una subclase A de la superclase B, es necesario preguntarse A es B? Puede decirse que cDManager es una Arraylist? No. cDManager no es una versin especializada de Ia Arraylist. La clase CDManager simplemente requiere reutilizar el servicio proporcionado por ia clase ArrayList. As, la segunda versin es e1 diseo apropiado. Este tipo de reutilizacin de cdigo se denomina reutilz{tcin de c-

'ebido a las clapor sus


puede ersona
reutilizacin de cdigo por composicin

digo por composiciru.

tanto clase

ejem-

:. Las
rbcla-

zliza-

Ms all del problema conceptual, la definicin de la clase CDManager como una subclase de Arraylist presenta debilidades prcticas. Debido a que es una subclase, el cliente de la clase CDManager puede llamar cualquier mtodo definido en la superclase ArrayList. Pero, tiene sentido que el cliente llame ei mtodo como capacidadSegura? Otra debilidad es la dificultad para cambiar la implementacin de la clase CDManager. Suponga que necesitamos modificar la clase Ce estructura de datos de Arraylist a HashMap para un mejor rendimiento. Con el enfoque de la herencia, cualquier cliente que utilice los mtodos heredados de ArrayList necesita reescribirios. Con el enfoque de composicin, el cliente que use slo los mtodos definidos por la ciase CDManager conti.nuaclase

de

r trabajando sin cambios. La modificacin tealizada de la clase ArrayList a la


HashMap es encapsulada en la clase cDManager y no afecta a 1os clientes.

f 3.8

Clcrlo de las califieaeiories de un (urso


Desarrollaremos un programa que ilustra el uso de Estudiante y sus subclases EstudianteGnad'ado y FstudianteNoGraduado. El programa leer los datos de los estudiantes de un archi|os

vo de texto indicado por el usuario, calcular las calificaciones del curso y mostrar
:..1'.!
,::::':':r:

t..,,='

,tj

resultados. Supondremos que el archivo de texto se ha creado utilizando un editor de textos u otra aplicacin. Por ejemplo, un profesor puede tener almacenadas las calificaciones de sus estudiantes en un cuaderno. En vez de calcular manualmente las calificaciones con lpizy calculadora, introduce los datos en un archivo de texto y aplica este programa para calcularlas. Otro escenario posible es que el profesor use algn tipo de software que le permita mantener registros de los estudiantes. Suponga que esta aplicacin no permite al profesor utilizar dife-

fi}

Captulo

'!

Herencia y polimorfismo

tl

no graduados y de los esturentes frmulas para calcular las calificaciones de los estudiantes a un archivo de texto y diantes graduados. En este caso el profesor puede exportar datos no graduados y de los estudiantes los de calificaciones las para calcular utilizar el programa archivos de texto para transfeestudiantes graduados usando las diferentes frmulas. El uso de de software' rir datos de una aplicacin a otra es una prctica comn en aplicaciones adoptaremos las polimorfismo, y el la herencia de empleo el en Para centrar la atencin forma diferenen implementarlas ejercicio como deja se y salida. de rutinas bsicas de entrada 5 se pide y ejercicio en el objeto archvo un en datos los guardar 4 se solicita te. En el ejercicio
usar la clase Scanner para entrada.

-d

Enunciado det Problema

'

Escribir una
ndca

del

curso

archivo de texto organizado de la forma en que se Las calificaciones continuacin y muestre las calificaciones finales del curso. y para los esgraduados para estudiantes los diferente se calculan ie forma

aplicacin

que lea un

tudiantesnogratduados,segnlasfrmulaspresentadasenlapginaTlT.Elformato
del archivo de texto es el siguiente:

n .

Se

utiliza una lnea por estudiante'

Cada Inea utiliza el siguienteformato:

<Tipo> <Nombre> <Examen 1> <Examen 2> <Examen 3>


no grgduado' <Nombre> donde <fipo> representa el tipo de estudiante' graduodo o examen. e! nombre y apellidos del estudiante y <Examen i> Ia calificacin del i-simo de moysculas o minsculas El final de Ia entrada se indica con la palabra FIN' E/ uso
es irrelevante.

c
En la

figura 'l 3.8 se muestra un archivo de texto de ejemplo'


clases del

Plan global
lmplementaremos una clase que

pfoglarna

1.

Lea un archivo de texto.


las calificaciones del-curso'

,,,2, Calcule

3. lmprima

los resultados.
<Examen
g7 90

<Tipo> <Nombre>
N
G G

1>

<Examen
78 95 77
85

2>

<Examen 3>
90

,Iohn Doe

Jil1

,Jones

87
68 80

N N

,Jack SmiEh Mary Hines Mick TaylQr

67
80

69

79

FlN

FiEura 13.8

los exmenes. G al inicio de la lnea Un archivo de texto que contiene los nombres y las calificaciones de graduado' representa a un estudiante graduado y N, a uno no

'0

3.8

Ejemplo de

desarrollo

74'g

:E

iOS eStU_

Ce texto v los y de los


ara transfe-

Para leer un archivo de texto, usaremos los objetos estndar de E/5 Fle, FlBeReader y BfferedReader. Para calcular las calificaciones del curso, usaremos las clases Esttdias'te, EstudianteNeGraduado y EstudianteGraduads definidas antes en el captulo. Las frmulas para calcular las calificaciones del curso se definen en sus mtodos calc.flaCaliflcacsr'Curso respectivos. Debido a que el archivo de entrada es un archivo de texto, para cada lnea

del archivo debe crearse un objeto EstrdianteGraduado o un objeto Estud!anteNoGraduado, de modo que sea posible llamar a su mtodo ealculaCalificacionCurso. Para almacenar los objetos estudiante creados (instancias de Estcdiaa"teGnadciado o de EstudianteNoGraduado), usaremos un arreglo de objetos Estudia'te para adquirir ms prctica
en el uso de arreglos.
ses auxiliares. La

:aremos las na diferenc 5 se pide

Para centrar la atencin en los tpicos de herencia y polimorfismo, utilizaremos dos claprimera es la clase OutputBox que se usa para mostrar las calificaciones del

'e se

,ne5
;

e5-

curso y guardar los resultados en un archivo de texto. Sus mtodos print y prirntln se utilizan para la salida y su mtodo saveToFile se usa para guardar los datos en un archivo de texto. El mtodo saveToFile guarda en un archivo designado el texto completo que se encuentra en un OutputBox. Si el archivo ya existe, entonces el contenido original del archivo se sustituye por el texto que se muestra actualmente en el OutputBox. A menudo necesitamos la capacidad de guardar el texto en un formato diferente. Por ejemplo, suponiendo que la informacin del estudiante incluye su nmero de identificacin, el profesor puede estar Interesado slo en guardar los cuatro ltmos dgitos del nmero de identificacin y las calificaciones del curso de modo que los resultados se puedan poner en un tabln. Si queremos guardar el texto en un formato diferente, es necesario implementar un mtodo idneo que cuente con
esa capacidad.
La segunda clase auxiliar es la clase MalrWindow. Nuestra clase principal se denominar CalculaCalificacion, y como otro ejemplo de herencia, hacemos que sta sea una subclase de MairWindow. De suyo, MainWindow es una subclase de JFrare, y posee la funcionalidad

ato

rombre>
?xamen.

tsculas

de colocarse en el centro de la pantalla (entre otras caractersticas). Los detalles de subclasificar la clase JFrarne se abordan en el captulo 14. A continuacin se muestra el documento de diseo de trabajo:

clases del

Documerto de diseo:

CalculaCalif icacion
Propsito
El objeto de control de alto nivel gestlona otros objetos del programa. La clase es un;ubclase de ia

programa

Clase
CalculaCalificacion

'

clase asistente

Mai-nwindow.

ESta clase'es la clase

principal instanciable.

OutpuLBox
'..:

Un outputBox se usa para mostrar los datos de entrada y las calificaciones calculadas del curso. stos son objetos de lgica de aplicacin para estudiantes. La clase Estudiante es una superclase abstracta. Estos objetos son ncesarios para leer datos desde un archivo de texto.

Bstu:-aate,r ,,: ' E s tudi anteNoGraduado,


. l,l
j:i l

EstudianLeGraduado
'

'

lnea

-'.::

,:

FiIe, FileReader, BuffefedReader

'

:=ii :::=.=l
, ;i. :: lt.
- ; I 1ir: ::.::,:
. .

.r=g-

:=-

742

Captulo

'!

Herencia y polimorfismo

13"8

No se muestfan las clases del sistema.

Figura 13.9

Oiagrarqa de objetos del programa CalculaCalificacion.

figura 13.9 es el diagrama del programa. A continuacin abordaremos los mtodos de CalculaCalificacion. Qu tpo de mtodos pblicos debe soportar la clase? Debido a que un objeto CalculaCalificacion es un objeto controlador de alto nivel, necesitamos un nico mtodo pblico para iniciar las operaciones. Definiremos un mtodo denominado procesaDatos que lleva a cabo las tres tareas principales. El mtodo main de CalculaCalifica(on llamar a este mtodo.
La

public static void main(StringlJ args) i calculacali.ficacion calculacalif = new Calculacalificaciono calculaCalif . procesaDatos O ; ]
El

mtodo procesaDatos es algo como esto:

this. setVisible (Lrue)


cuadroSal ida . setVis

/hacer visible 1a ventan principal y


OutputBox
.{i. '

ible ( true)

boolean exitoso = leeDatos O ;

I *

if

(exiroso) { calculaCalif icacion

);

imprimeResultado ( ) ; else ) { imprime mensaje de error rError en archivo de entrada',,.

]
El mtodo leeDatos devuelve true si los datos de entrada se leen correctamente desde un archivo de texto y el arreglo de objetos Estudiante se crea apropiadamente. A continuacin se presenta el documento de diseo de CalculaCalificacion:

diseo d paso 1

*&*

'13,8

Ejemplo de

desarrollo 743

Doeusmesto de dseo: La e$ase

calculaCalif ica-cion
Propsito
Crea e inicializa tos objetos usados por un objeto

ffltodo <consLructor>
procesaDatos

Visibiidad

publ ac

CalcuIaCal if icacion.

public private private private

5e muestra a s mismo y realiza las tres tareas principales.

leeDatos

Abre y lee datos del archivo de texto y rea un arreglo de objetos EstudianLe a partr de los datos de entrada. Si la operacin es exitosa, devuelve true. Explora el arreglo de objetos calificaciones del curso.

calcul-auaI].!acac].0n
r-mprame-

EsLudiante

y calcula las

lmprime la informacin de los estudiantes

Resultados

junto con las calificaciones calculadas en un output Box.

mtodos rjeto connes. Defi-

Desarrollaremos el programa en cinco pasos incrementales:

1. Comenzarconel esqueletodel programa.Definirlosesqueletosdelasclaseseal<.laCallficacion.

:ipales.

El

2. lmplementar el mtodo imprimeResultados. Definir cualquier otro mtodo necesario


para la implementacin de irnprirmeResuEtados.

3. lmplementar el mtodo calculaCalifi(aci@n. Definir cualquier otro mtodo


para la implementacin de calcu[aCaEificaclor.

necesarjo

:ion O ;

4. lmplementar
5"
La

el mtodo leeDatos. Definir cualquier otro mtodo necesario para la implementacin de leeDatos.
Finalizar y buscar mejoras.

1 -,

utBox

implementacin del mtodo ms difcil, leeDatos, lo pospondremos hasta el final. Algunos programadores prefieren tratar los aspectos ms difciles del programa al principio, y no hay ninguna regla estricta que permita ordenar los pasos de la implementacin. El lector debe ordenar los pasos en la forma en que se sienta ms cmodo. Sin embargo, esto no significa que usted puede implementar los mtodos en forma aleatoria. Siempre debe planificar cuidadosamente lcs r:asos de la implementacin, de modo que sgan una secuencia lgica. Para este programa, empezamos con la rutina de salida, de modo que sea posible utilizar la rutina de salida final para probar otros mtodos, en vez de definir una rutina de salida temporal para efectos de depuracin.

Desarrollo de! paso 1: esqueEeto de! progran'la


diseo del paso 1

Comenzaremos con los miembros de datos y los constructores para la clase CalculaCalifieacion. Empezamos con los siguientes miembros de datos:

:sde un
lcton 5e

private outputBox cuadroSalida; / /pata la salida


private Estudiante [] lista
/

/para mantener la informacin //de Los estudi-antes

V44

eaptulo

l3

Herencia y polimorfismo

'!

3.8
La creacin de los cuatro prlmeros objetos es drecta, aunque necesitamos pensar un en el arreglo [ista. Cul debe ser el tamao cie este arreglo? Hay varias posibilidacles:
'l

Crear un arreglo de tamao arbitrario; por ejemplo, 25.

2. 3.

Dejar que el programador pase el tamao en el constructor..


No crearlo en el constructor. Modificar el archivo de texto de entrada para incluir el tamao de un arreglo en la primera lnea.

pu:

]
pu.

La opcin 3 no es nada atractiva porque requere un cambio en la especificacin del problema. Adems, requerir que esta informacin est presente en el archivo de entrada hu.* j, n, difcil la tarea al usuario, quien tiene que ocuparse de contar el nmero de lneas que contien; el archivo. Esta tarea tan tediosa debe dejarse a la computadora. As, implementaremos las Qpciones 1 y 2.Si los datos no pueden ajustarse a un arreglo de tamao preasignado, entonces utilizaremos la tcnica que se analiz en el captulo 9 para expandir el arreglo. Declararemos una constante

private

stat j.c f inal

nt

TAIv1ANIO_PREDETERM

= 25;

llPr
p

y los dos constructores se declararn como sigue:

public
this
)

Cal-cul-aCalif icacion
(TAI4ANIO-PREDETERM)

O
;

publc CalculaCalificaci-on(int tamanioArreglo) { super O ; / /Ilama expl-cj-t.ament.e al construct.or de la


superclase

cuadroSalida = new Out.putBox(this) ; lista = new Estudi_ante ltamanioArregloJ


)

cdigo del
paso
1

Observe que no es posible crear archivoEntrada, lectorArchivo y lectortsuf sino hasta que se abre el archivo. Estos objetos los crearemos en uno de los mtodos que definiremos nls tarde. Para el esqueleto del programa incluiremos sentencias de salida temporales en los mtodos privados para comprobar que sean llamados correctamente en el orden idneo. A continuacin se muestra el esqueleto:

Desarrol-lo de ejemplo del captulo 13 : Calcular' las calificaciones de Estudiantes no graduados y Est,udiantes graduados Archivo : Cal-cuf aCalif icacion. j ava

'J:=:

J.o

EJstf

tfxu G ttgiar(lo

,15

//--------PASo 1--------// class Cal-culaCalificacion extend.s MainWindow { private st.atic final inL TAMANIO-PREDETERM = 25; privat,e OutputBox cuadroSalida,. private Estudiante[] lista; public CalculaCal-ificacionO i This (TAMANIO_PREDETERM) ;
)
n del pro_ hace.ms

cluir el ta_

contiene
emos las' 3ntonces
,

publc CalculaCalificacion (int tamanioArreglo) { superO; //Ll-ama explcitament.e al constructor de 1a superclase cuad.roSalida = new OutputBox(this) ; lista
)
/ / --/ / PrlrlcLpaL

= new Estudiante ltamanioArregloJ

//----

public static void main(Stringll args) { Cal-curaCalificacion calculacalif = new Carculacalificaciono calculaCalif . procesaDat.os ( ) ;
)

public void. procesaDatos O { this. setvisible (true) ,


cuadroSal ida . set.Visibl_e ( true),.

'i

boolean exitoso = leeDatos O ;

if
ue 5e
arde.

calculaCali-f icacion ( ) ;
rtoonti-

(exitoso) i

imprimeResult.ados ( ) ; ) else { cuadroSalida. priritln ( r'Ejrror en archivo de entradair);

]
O

private void calculaCali_f icacion


)

cuadroSalida. println ('Dentro de calculaCalificacion,,) ; / /tBy.P

private void imprimeResultados

O{ ,,)

cuadroSalida.println (,"Dentro de !-mprimeResultados

/ /TEMI

eaptulotr3

Herenciaypolimorismo

3.8

private boolean leeDatos ( ) { cuadroSalida.println(rtDenLro de leeDatos',) ; return true;

/ /TEMP

)rueba def laso 1.::...

Ejecutamos la clase principal y el esqueleto de la clase CatculaCalificacon para efectos de verificacin. Una vez que se ejecuta lo anterior, en la pantalla veremos la ventana principal de alto nivel (CalculaCalificacion) y un cuadro de salida, as como los siguientes mensajes en el

OutputBox:

Dentro de leeDatos Dentro de calculaCalificacion Dentro de imprimeResultados


Desarrollo del paso 2: lmplementacin delmtodo imprimeResultados
liieno

rso,2:

Jel , ,'. : .," '

En el desarrollo del segundo paso, aadimos una rutina que ubica el resultado en un cuadro de salida (cuadroSalida). Para implementary probar este mtodo, necesitamos crear el arreglo lista. lncluiremos cdigo temporal dentro del mtodo leeDatos para construir y probar el arreglo lista. Podemos utilizar los siguientes ciclos for:

for I
primera mitad del reglo tiene estudiantes : graduados.
r

(int i = O; i < i5; i++) { listalil = new EstudianteNoGraduado0; listalil.estableceNombre( "No graduado # " + i

listalil .estableceCalificacionExamen(1, 70 + i) Ii-stalil .estableceCalificacionExamen(2, 75 + i) listalil .estableceCalificaci-onExamen(3, 8O + i)

]
r--------------- for (int i = 15,. i < TAMANIO PREDETERM; i-++) t lista [i-] = new EstudianteGraduado ( ) ; r segunda mitad del lista [i] . estableceNombre ( "Graduado # " + i reglo tiene estudiantes
I

'aduados.

lista Ii] . estableceCalificacionExamen (1, 80 + i) lista Ii] . estableceCalificacionExamen (2, 85 + i) lista Ii] . estableceCalificacionExamen (3, 90 + i)
)
para crear una lista temporal para efectos de depuracin.

ry_
+4!ts=

3,8

Ejemplo de

desarrollo 747

A continuacin disearemos el mtodo mpninreResultados. Cuando se llama a este mtodo, tenemos construido el arreglo !ista. El mtodo recorre el ari.eglo y recupera los clatos clel estudiante utilizando los miodos obten"[\ior'hre, obtenCalifieaconcrnso y obtencalificacionExamen. Expresado en pseudocdigo, se tiene lo siguente:

@
efectos de incipal de ajes en el

ror caca elemento i en eL arteglo _7.:sta { imprimir ef nombre de fista[i]; imprimir fas califjcacianes def examen de lista Ii] inprimir fas cafificaciones dej curso de listalil; saltar a Ja siguiente Jnea;
^* ^-J-. ^l -

)
Cmo debe terminar el ciclo? Primero necesitamos darnos cuenta que el arreglo llsta puede estar lleno o no estarlo. Por ejemplo, su tamao predetermnado es 25, pero el nmero real de elementos puede ser menor que 25, de modo que utilizar el valor de la lista.length no funciona. Debido a que lista es un arreglo de objetos, una forma posible de expresar el ciclo es como se muestra a contnuacin:

. while (listalil

l= null) { //:-mprim:-r 1a informacin de list.atil

adro de arreglo el arre-

i
Un problema con este ciclo wl'ile es que se debe tener por lo menos un elemento vaco en el arreglo para que el ciclo termine correctamente. Esto podemos mejorarlo usando el valor de length como

whil-e (i < lista.length

a& listalil

l= nul1) {

i
Otra posibilidad consiste en mantener un contador, que se fija en el mtodo leepatos. contador es un miembro de datos de tipo int. Esta variable se denominar contadorgstcrda'tes. Entonces, el ciclo de procesamiento se convierte en
Este

for (int i = 0; i < contadorEstudiantes; i++) { //imprmir la informacj-n de lisra lil ]


Adoptaremos este enfoque debido a que poseer esta informacin del contador es de utilidad para otros propsitos. Por ejemplo, si queremos calcular el porcentaje de estudiantes aprobados, podemos usar contadonFstudiantes para hacerlo. Si no tenemos esta variable, entonces cada vez que sea necesario calcular el porcentaje, tendremos que contar el nmero de estudiantes en el arreglo lista. Finalmente, para imprimir la informacin del estudiante de modo que los datos aparezcan alineados correctamente, utilizaremos el carcter de control \t (que significa tabulador). para

748

eaptulo

i3

Herencia y polimorfismo

3.8
jor. Para una salda ms elaborada, puede usarse la tcnica de formateo que se analiz en el
una simple salida como sta, utilizar tabuladores para Ia impresin de resultados funciona me_

cdigo del
paso 2

captulo 6. A continuacin presentamos el Cdigo del paso 2. Observe que aadimos una declaracin para un nuevo miembro de datos co'ltadorEstudartes, y que este miembro de datos se inicializa en 0 en el constructor.
.':x;.:j;::]+:5j

/*

Desarrollo de ejemplo de1 captufo l-3: Calcular calificaciones para estudiant.es no graduados y estudiantes graduados
Archj-vo : CalculaCalif icacion. j ava

r^-

tl

//----

-----pASO 2----

------//

/t

class CalculaCalificacion extends MainWindow { private int contadorEstudiantes public CalculaCalificacion(int


contadorEst.udiantes = 0;
;

tamani-oArreglo) {

i
Effi

I private void imprimeResultados O { for (nt i = 0; i < cont.adorEstudiantes; i++) { //imprime un estudiante cuadroSalida.print (1isa Ii] .obtenNombre O ) ; for (int, numeroExamen - 1i numeroExamen <= Estudiante.NUlt_OE_UXanUeWfS;
numeroExamen++) {
prueba del
paso 2

cuadroSalida.print ( "\L" + lista Ii] . obLenCal_ificacionExamen


(numeroExamen) )
,'

cuadroSalida. println )

("

\t,, + lista Ii] . obtenerCalif icacionCurso ( ) ) ;

diseo d paso J .

private boolean leeDatos O { cuadroSalida.prnt1n(',Dentro de leeDatos,t) i

/ /'IEMP

'

3"8

Fjemplo de

desarrollo V49

/ /TEMP erear un arreglo temporal Iista para // probar e1 mtodo imprmeResultados //

for (inL i = U; r < 15; r++) t lisLa Iil = new EstudianteNToGraduado O ; lista Ii] .est.abfeceNombre("No graduado # ', + i lista Ii] . estableceCalif icacionExamen (1, 7 +1 lista Ii] . estabLeceCalif icacionExamen (2, gO +lIista Ii] . est.ableceCal- j-f j-cacionExamen (3, 9O +1
O

);

); ); );

for (int i = 15; i < TAMANIO_PREDETERM; j-++) { lista Ii] = new Est.udiantecraduado O ; lista Ii] .estabfeceNombre("Graduado # " + i ); lista Ii] . estableceCalificacionExamen (1, lista Ii] . estableceCalificacionExamen (2, lista Ii] . estableceCalificacionExamen (3,
)
BO

B5 +

90 +

i ); i ); i );

contadorEstudiantes =

TAMANIO pREDETERM;

return true;

prueba del
paso 2

-\-F e

=)

En este paso verificamos dos elementos. En primer lugar, el mtodo temporal leeDatos incluye la creacin de objetos estudiante y llamadas a sus mtodos. Lo ejecucin correcta comprobar que se est incluyendo la clase de estudiantes correcta y que sus mtodos se estn usando adecuadamente. En segundo lugar, el mtodo irnprirneResultados debe mostrar la salida segn se espera. Debido a que no se ha implementado el mtodo calculaCa!ifieacion, para las calificaciones del cursc se vern cuatro asteriscos. Necesitamos ejecutar varias veces el programa y ajustar el formato. Tambin, es importante intentar diferentes valores para los nombres y calificacones de los exmenes antes de proceder al siguiente paso.

::) ) ;

Desarrollo delpaso 3: Implernentan del mtodo calculaCa ificacion


I

diseo del
paso

.:

La funcionalidad para calcular las calificaciones del curso se encuentra dentro de las clases estudiantes; especficamente, dentro de los mtodos calculaGatificacionCrrso respectivos de las clases EstrdianteGrad.ado y EstudlanteNoGraduado. En consecuencia, todo lo que necestamos hacer en el mtodo calculaCalificaeon es explorar el arreglo lista y llamar a los elementos del mtodo calctlaCalificacon. Esta sencillez es un resultado directo del polimor-

fismo.

75O

Captulo

13

Herencia y polimorfismo

13.8
cdigo del
paso 3

A continuacin presentamos el listado completo. La nica aadidura es el mtodo calcu-

laCalificacion.

Desarrollo de ejemplo del captu1o 13: Calcular las calificaciones Estudiantes no graduados y Estudiantes graduados Archivo : CalculaCal if icacion. j ava
/

de

class CalculaCalif icacion

/ ---

---PAso 3e:<tends

;;,;;;; i

----'//

private vod calculaCalificacionO { for (int i = 0; i < contadorEstudiantes; i++) lista Ii] . calculaCalificacionCurso O ;
)
-1, -

c
n

prueba del
paso 3

Repetimos las mismas rutinas que en el paso 2. En vez de ver los cuatro asteriscos para la calificacin del curso, deberamos ver los valores correctos. Para facilitar la verificacin, es posible fijar las calificaciones para todos los estudiantes. Es necesario asegurarnos de asignar calificaciones de modo que los estudantes estn aprobados o no aprobados. No olvide probar con valores extremos como cero para las califica_ciones.$_e_191r_es e{Te!_es. Qu ocurre con calificaciones negativas? La clase Estudiante las manejara correctamente? Si tenemos graves problemas con la clase Estudiante, puede ser necesario suspender el desarrollo hasta que se
haya corregido esta clase.

Desarrollo del paso 4: lmplementacin del mtodo leeDatos

13,8
e1

Ejemplo de

desarrollo

751

se

inprimir un mensaje de error;


Utiiizaremos un objeto de tipo.JFile(hooser del paquete estndar javax.swing para per mitir que el usuario especifique el archivo. 5i el usuario cancela este cuadro de dilogo, entonces se devuelve nq.!1. En este caso, imprimiremos un mensaje de errory se parar. Si el usuario especifica un archivo, entonces esta informacin pasar al mtodo privado constrtayeLista, que leer los datos del archivo indicado y construir el ar:reglo lista. El mtodo coa'lstrulyelista leer una lnea de datos a la vez del archivo designado. y para cada lnea de datos, crear un objeto estudiante idneo (una instancia de la clase EstrdiarteGraduado si el tipo es G y una instancia de Estq.dianteNoGnaduado si el tipo es N). El contador contadorFsttdiantes se incrementar por 1 despus del procesamiento de cada lnea. Cuando la lnea contiene el terminador F!N, el mtodo completa su ejecucin. Si los datos de una lnea no se disponen segn el formato especificado, entonces se ignora la lnea. El mtodo, expresado en pseudocdigo, es como se presenta a continuacin:

try { fijar

TectorBuffer para 7a entrada;

while ( lhecho) { Inea = obtener 7a siguiente 7nea; if (fnea es FrN) { hecho = true; ) else { estudiant.e = creaEstudante(Iinea)
I

W
rara la s posica

creaEstudiante devuelve null si !inea no se ajusta al formato designado.

if

(esLudiante l= nuI1) { listaIcontadorEstudiantes] = estudiante; //se aade a l-a list.a contadorEstudiantes ++ ;

]
)
)

lifi-

tr con
n calitraveS

ue 5e

] catch iiExceptiorr e) { lnprinir mensaje de error;


)
El bloque try-cateh se utiliza porque la creacin del objeto tectorBuffer de tipo ErffenedReader de un nombre de archivo concreto puede dar por resultado una excepcin. En vez de las clases FileReader y BufferedReader puede utilizarse la clase Scanner. El mtodo creaEstudlante acepta un argltmento de tipo StrinE, que es una lnea del archivo de entrada, y de-

,S

eX-

vuelve una instancia ya sea de EstudianteGraduado

o de Est.dianteNoGnaduado,

dependiendo del tipo especificado en la lnea. 5i en la lnea de entrada hay un error, entonces reaEstudiante devuelve nrll. En vez de terminar todo el programa, simplemente se gnorarn las lneas que no cumplan con el formato especificado.

'

752

Captulo

13

Herencia y polimorfismo

En una forma bastante simplificada, el mtodo creaEstudiante es algo como lo que muestra a continuacin:

se

nuevoEstudianteConDatos devolver null si lineaEntrada contiene


datos no vlidos,

tipo = primer eTemento de TineaEntrada; if (tipo.equals (No-cRAD) | | tipo.equals (GRAD) ) { estudiante = nuevoEstudianteConDatos ( lineaEntrada else ) { //s" ha enconLrado un L.ipo no v1ido estudiante = null; ]

);

return estudiante,'

(String) el primer elemento. Cm<j puede hacerse esto? El mtodo nuevoEstudianteConDatos, que crea una instancia de EstudianteGraduado o de EstudianteNoGraduado y le asigna datos, tambin requiere una operacin para extraer elementos individuales de la lnea. Podemos escribir nuestra propia rutina de procesamiento de cadenas para analizar la lnea y extraer los datos sobre el tipo, el nombre y las calificaciones de los exmenes. Sin embar!jo, hay una mejor solucin. Podemos utilizar una clase estnda r denorinada StringTokenizer del paquete java.util. Para explicar esta clase haremos una rpida digresin. En vez de usar la clase StringTokenizer, podramos utilizar las tcnicas de correspondencia de patrones con las clases Pattern y Matcher. Sin embargo, la clase StringTokenizer es idnea para un caso como ste, donde se qulere extraer elementos
La primera sentencia requiere extraer de la lnea de entrada

(tokens) de una cadena dada.

' fokenizer.

sq;in;-

' ,
,

Un objeto de tipo StringTokenizer se utiliza para extraer tokens de una cadena dada. Un token es una cadena de caracteres separada por caracteres delimitadores, o simplemenle delimitadores.Cualquier carcter puede ser designado como delimitador, aunque el delimitador de

mayor uso es el espacio. En forma predeterminada, un objeto de tipo StringTokenizer usa un espacio en blanco (blanco, tabulador, nueva lnea o retorno de carro) como su delimitador. A continuacin se presenta un ejemplo. El cdigo siguiente:

String lineaEntrada = itYo bebo 100 Eazas de caf cada maana."; StringTokeni zer a.nalizador = neyr StringTokenize- (.i.ineaEntrada) while (analizador.hasMoreTokens O ) i ' System.out.prnttn(analizador.nextTokenO ) ;
)
imprimir la siguiente salida:
Yo

bebo
100

Lazas
de

'f

3,8

Ejemplo de

desanollo

7Sg

caf
cada
maana
.

vor, consulte el manual de referencia de'ava.utt para obtener mJs nformacin sobre stnimgT'okenzer.

El mtodo fiasMore'rokens devuelve tnee si en el analizador no quedan ms iokens, y el mtodo nextToken devuelve el siguiente token que est en el analizador. El mtodo nextToken lanza una excepcin f{osuchElenentException si ya no hay ningn token a devolver. porfa-

Est muy bien si usted ya sabe algo sobre

Cmo

e EstuI

operutina ombre
)a

elcaso, se ha quedado sin suerte. podra terminar programando lu rrn.oJiuJ de StringTokenizer usted mismo, vorviendo a hacer." J. r" zado' Lo anterior siempre constituye un reto pu' todo r mundo, ,or" principiantes. siempre que encuentre una situacin que aparent;;";i;;;;;;; una tarea comn de programacin, primero consulte los manuale,
de Java APt.Tambin puede consulrar con sus

stringTokenlzer, pero si an no es ste

utilizar
a

clase
Ia

zar ias

'go,

entos
,d.

o :ol :, ilsifuctor para efectos de orientacin. euiz eltoi sepan ;d;;;;;; adquirir el hbito de navegar en los rnanuales de referencia ouluuu t', o.;;J; que tenga un conocimiento general sobre las clases estndar. El meollo det asunto consste en buscar clases existentes para reusarlas.

condiscpulor.;;;r"r;.lJn-.'o"

qr.; i"hu.;'; * ;;;;, J"-r"f.;#;

un

elimicr de
;a Lln or. A

diante puede expresarse como

Ahora volvamos al diseo. Utilizando un objeto StringTokenizer, el mtodo creaEstrse muestra a continuacin:

StringTokenizer anal_izador = new StringTokenzer(linea)


al v rry i -^ uLr tapo
/.

tty

{ tipo = analizador.next.TokenO

if (tipo.equals(NO_GRAD) | | tipo.equats(GRAD) ) { estudiante = nuevoEst.ud.j-anteConDat.os (tipo, anal izador) ) else { //=" ha encontrado un tj_po no v1ido estudiante = nul1;
)

return estudi:na.
El mtodo privado nuevoEstudianteconDatos acepta un argumento de tipo string que especifica el tipo de estudiante y un objeto StringTokenizer. El *todo crea una instancia de

catch (NoSuchElementException e) { estudiante = null.

/n" hay elemento

: ti

754

Captulo

13

Herencia y polimorfismo
' ..i: .,:)l!:r:i
ri i|!!:l :rr,fi-rr'lri'ii'

'3.8
EstudianteNoGraduado o de EstudianteGraduado y asigna los datos al objeto llamando
manera repetida al mtodo nextToken de StringTokenzer:
de

rrv

/tipo y analizador son los parmetros f (tiPo. equals (NO-GRAD) ) { estudiante = new EstudianteNoGraduado O ; else { ] estudante = new Estudiantecraduado O ;
) estabLecer el nombre deL estudiante //u:-Ilzar {

imPort imPor' imPor

analizador. //nextTokenO Para extraer //datos'de una linea

class I
l

establecer Las calificaciones de7 estud'ian:e ) catch. (Excepcin e) { //genetada por analizador'nextTokeno estudiante = nulI // o Integer'parselnt("')
)

reuurn estudiante; '


El

do.ur"nto

de diseo para la clase CalculaCalificacion ahora incluye tres nuevos mtodos

privados:

Doturnnt'Ea*iO:' cli'Ca1
Mtddo:i,,'i':,
.:r':
,

uiCii-ricai

:.::

: :i :ia,ji.::.

vsibiidad,
.r)::r,t:l.::::t'

r: :l : -'j :..:, i.r

'.

: :-r

::.,
;1':,,:i,r:

.,
i_

::'ou'n'
Le una lnea de datos dl archivo designado a la vez; y para cada lnea de datos, crea un objeto

consLruveLista
l r I r , ,: :t:l .;i

pi'1vate.
ii i
:ii.:.: .r rri.rl..,rr.. ' ii .1::

.:i.:':l i l
, l .

rrriri,,ili,l( lli.:r'l

estudante idneo.5i fos datos en una lnea no se ajustan al formato designado, entonces se lnea. ionora:la ..:

creaEistrudl-anE e : , t,rri
r ll l.l.i.i;ii',rt:il.:i ,. ,:: ,' l :: t. I I :i '1 ..'..

bili+i
I

Cra un objeto estudiante llamando a nue voEstudianteconDatos si el tipo de lnea

l,:.rr-l

ri.,..,.,r.1,.11

:.-

.'il

,llr'i

'esiiat
.rl-l.f

de entrada es N o G. En caso de xito, devuelve al cr,.u nlCaio intrario, devuelve

I
I

nuevoEstudianteConDatos
li:

p-fivate
. : i::t:r : ii r:

.,.,r,'

',.', -,, :i:r:i::


i

ir:

iir;i

Cie un instancia derEstudianteNocra duado o de EstudianteGraduado y asigna datos al objto llamando.de manera repetida a nexLToken de Stringlokeni zer.

*#s

13.8 Ejemplodedesanob
cdigo del paso 4

*;

A continuacin se presenta el cdigo del paso 4 completo:

Desarro]1o de ejemplo de1 captulo 13: Calcular las calificaciones de estudiantes graduados y estud.iantes no graduados Archivo : Calcu1aCalif icacion. j ava

rdor.

import import import

j ava. io. * ;

java.util.*;

j avax. swing. *

,.

eno

ltodos

//----- pAso 4 ----:--------// class CalculaCalificacion extends Mai.nWind.ow { private static f nal int TAIvIANIO_PREDETERM = 25; private stat,ic final String NO_GRAD = ,,Nr,. private tatic f inal String GRAD = ',cu privat,e stsatic finaL string FIN_DE_ARCHIVO_STR = ',FIN',; private OutputBox cuadroSalida,. private Estudiante[] lista; private int contadorEstudiantes ; public calculaCalificacionO t thig (TAMANTo_PREDETERM) i
,,

pubLic calculaCalificacion(int tamanioArreglo) t superO; // Llama explcitamente al constructor de Ia superclase cuadroSalida = new OutputBox(this) ; lista = new Estudiante ltamanioArregloj ; contaclorEstudi-antes = 0;

/,/ rrincipal

//----

//---

public static void main(StringlJ args) { Calculacalificacion calculacalif = nw calculaCalificaciono calculaCalif . procesaDatos ( ) ;
)

public void procesaDatos O { setVisible (true) ; cuadroSal ida. setVisible ( t,rue) ;

rF14*

t6

eaptulo

13

Herencia y polimorfismo

3"8

boolean exitoso = leeDatos O ; if (exitoso) { calculacalif icacion ( ) ;


imprimeResuLtados ()
;

] else {
)
J

cuadroSalida. pri-nt1n (,'Error en archivo de entrada")

private boolean construyelista (String nombreArchivo) { String lineaEntrada; Estudante estudj-ante ;


t,.a-Le

archivoEntrada;

FileReader
Buf f eredReader

lectorArchivo; lectorBuf ;

boolean estado - true; boolean hecho = false;

rry {
archivoEnt.rada

lectorArchiwo lectorBuf

new File (nombreArchivo) ; new FileReader (archivoEntrada) ; new Buf f eredReader (lectorArchivo)

while

lhecho) {

lineaEnt,rada = lectorBuf. readline O ; / /Lee una lnea

if (lineaEntrada.equalslgnoreCase(FIN hecho = true,.


)

DE ARCHIVO STR)

else { estudiante = creaEstudiante(lineaEntrada) ; if (est.udiante t= nuII) { lista IcontadorEsLudi-antes] = estudiante,. . contadorEsludiant,es++;


)

I //
)

)
whil-e
O
;

lectorBuf. close

catch (IOException e) { est,ado = false;


)

qP**

13.8

Ejemplo de desarrollo

757

returr estado;
)

private woid calculaCaLificacionO { for (int i = 0; i < contadorEstudiantes; i++) t lista Ii] . calculaCaljficacionCurso O
,.

)
1

private Estudiante creaEstudiante(String linea) { Estudj_ant.e estudiante; StringTokenizer analizador = new StringTokenizer(1inea) String t,ipo; trra { tipo = analizador.nextTokenO ; if (tipo.equals(No_cRAD) I I tipg.equals(GRAD)) {

estudiante = nuevoEstudi"anteConDatos (tipo, analizador) ) else { estudi-ante = nu1l; ) catch (NoSuchElementException e) { estudiante = nu1l;
) )
/

/no hay elemento

return est.udiante;
f

private Estudiante nuevoEstudianteConDatos (String tipo, St.ringTokenizer analizador) { EsLudiante est,udiante


;

rry { if

(ripo.eguals(No_cRAD) ) { estudi_ante = nev, Estudian.teNoGraduado O

,.

) else { estudiante = new Estudiant.eGraduadoO

/,/establece:: e1 nombre deI estud.iante String nombre = analizad.or.nextTokenO ; String apellido = analizador.nextTokenO ; estudiante.estableceNombre(nombre + il tr + apellido) ; //estaUtecer 1as calificaciones de1 estudiante for (int numeroExamen =, 1i numeroExamen <= Estudiante.NUM_DE_EXAMENES i numeroExamen++) {

-{&

P58

CaptN.[o

13

Herencia y polimorfismo

t3.8
jr*in.;!'.x.*x;.sr:jri*rj$Fr+):i:Fis{::i;}:4*ja3s+taH:g;*iar.J::1i*t;i:*i}:i*:i;!i::il:+.|jiii*ii!!,j,54 es

'jaii!,ii:,.-a!ij;:

tudiant

e . es

tabl eceCal i f i cac i on (numeroExamen, Integer.parsefnt (ana1zador. nextToken

O))

] ] catch (Exception e) { //anal izador.nextTokenO o / /lnteger.analizadorlnt (. . . ) estudlant.e - nul1;


)

Lanza una excepcin

return estudiante;
)

private void imprimeResultados O t for (int i_ = 0,. i < conLadorEstudiantes,. i++) { / /imprimir un estudiante cuadroSalida.print (IisLa Ii] . obtenmombre O ) ; for (int numeroExamen = 1,. numeroExamen <=
Estudiante.NIM_DE_EXAMENES

numeroExamen++) {

cuadroSalida . Print ( 'r \L " + 1ist.a Ii] .,obtenCaIif icacionExamen (numeroExamen) ) ,

cuadrosalida. println

il

\t,

" + lista Ii] . obtencalif icaci_oncurso

);

private boolean leeDatos O { / /obtener el archivo a abrir ,JFleChooser seLectorArchivo = new ,fFileChooser(". ; ") //empezar 1a lista desde e1 dj-rectorio actuaL int, regresaVal = select.orArchivo. showOpenDialog (this),. boolean resultado = false i if (regresavll ==,fFiIeChooser.AppROVE OPTION) {
s

trins ":t:;::::lll"nr,"

if
)

. serselecredFi (nombreArchivo != null) t

1e ( )

serAbsolureparh ( ) ;

resultado = construyelista (nombreArchivo),;


returr. resultado;
)

ffi

*ffi

prueba del paso 4

siguientes:

En este paso ejecutamos una rutina de prueba ms completa. i\jecesitamos ejecu:=: = programa para varios tipos de archivos de entrada. Algunos de los contenidos posibles scn ios

Datos de prueba del paso 4 Arc!'ivo de pnueba

FEop6sito
Probar el caso normal.

:pcin

Archivo con 5 a 20 entradas de informacin del estudiante con todas las lneas en el formato
correcto.

Archivo con 5 a 20 entradas de informacin del estudiante con algunas lneas en formato
tncorrecto.

Probar leeDatos y los mtodos'de soporte para manejar correctamente el caso de error.

Archivo sin entradas. Archivo con ms de 25 entradas.

Probar que el mtodo construyeLista maneja correctamen_ te el caso de error.


caso en que el nmero de entradas es mayor que el nmero predeterminado para el arreglo de la tista.

Probar que leeDatos y los mtodos de soporte manejan el

+) i
n));
'l
::::
,l

Desarrolto de! paso S: firaE!zac!n y mejoras


revisin del programa

Como siempre, finalizamos el programa corrigiendo los posibles errores inconsistencias o mtodos no terminados. En esta ltima etapa tambin se buscan las posibles mejoras. Una mejora que siempre se busca est relacionada con la longitud de los mtodos. Aunque no hay reglas que especifiquen la longitud, un mtodo no debera ser ms grande que una pgina. Los m_ todos constrtryelista y nuevoEstudianteconDatos se aproximun . urtu mximo. Si observamos que un mtodo se est haciendo ms grande en la etapa de codificacin, entonces necesitamos volver a pensar en el diseo. Por ejemplo, si el mtodo construyeLista se vuelve demasiado grande, entonces podemos definir un nuevo mtodo que lleve a cabo una porcin del mtodo, como desplazar la sentencia if-then-else del mtodo a un nuevo mtodo. Un problema que queda (y que debi identificarse en la prueba del paso 4) es el mtodo faltante para expandir el arreglo tista cuando el archivo de entrada incluye ms entradas de estudiantes que las correspondientes al tamao predeterminado igual a 25. Este mtodo se deja corno elerctcio 3. Tarnbin dejanros con":o ejerclcios algunas de las mejoi-as posibies.

,:Resunrn
La herencia y el polimorfismo son poderosas caractesticas de lenguaje para desarrollar cdigos extensibles y modificabies.

El mecanismo de herencia se utiliza para compartir cdigo comn entre clases re_ lacionadas.
ffi

La herencia es diferente de la interfaz Java, que se utiliza para compartir comporta_ miento comn entre clases no relacionadas.

'6@

Captulo

13
a
a

Herencia y polimorfismo

llamar al constructor en forma predeterminada de ta super"tase. La clase estndar descrita o utilizada en este captulo es

Ei tercer modificador de visibilidad es el modificador protected. En caso de que no se creen instancias_a partir de una superclase, entonces ra super= .; clase debe definirse como una clase abstach. I os mensajes polimrficos indican que el mtodo ejecutado en respuesta al mensa_ je vara segn la clase a qu" p"rten"e el objeto. La primera sentencia en un constructor de una subclase debe ser una llamada al cofistructor de la superclase. si la sentencia requerida no se planteu " **"iul"_ plcifa, entonces el compilador de Java inserta automticamrt" r","n;;;i;;;; - -stringrotenizer.

i'
I I

superclase y subclase herencia herencia y constructores herencia y modificadores de visibilidad

superclase abstracta mtodos abstractos

polimorfismo
herencia contra interfaz

ir

1.

Considere las siguientes definiciones de clase. Identifique sentencias invlidas.

cLass Coche {

public SLring protecled int private St.ring

marcai peso;

color;

class CocheElectrico extends Coche private in! horaRecarga; public CocheEle.ctrico O {


)

//consEructor de copia public CocheElectrleo (CocheElectrico coche) i this.marca = coche.marca; this.peso coche . peso; this. color = new String(coche.color) ; this.horaRearga = coghe . horaRecarga,.

aF@

Ejercicios 761

class PrlncipalPrueba { pub!.ic static vod main (String[] args) { Coche miCoche; CocheElectrico miCocheElectrico ;
miCoche = new Coche O
mi-Coche.
; ;

marca = " Chev-yr' micoche.peso = 1-000; miCoche - color = "Rojo" i

miCocheElectrico = nerl CocheElectrico o miCoche.marca = "Chevy"i micoche.peso = 500; micoche. color = "Plateado" ;

]
)
2. Considere las siguientes definiciones de clase. Identifique las llamadas in\'lidas al constructor.

class Coche { public Strlng marca,' protected int peso; private String color; private Coche (String marca, int peso, Strng color) { t,hie.marca = rrrdrCdi this.peso - peso; this.color = color; ) public Coche O i this (rDesconocidorr , -1-, "blancot') ;

]
class CocheElectri-co extende Coche private int horaRecarga; public CocheElectricoO { . this (10) ;
)

private CocheElectrico(int carga) t supero; horaRecarga = carga;


) ) cl-ass PrinclpalPrueba {

public static void main (string Il args) { Coche miCochel, miCoche2; CocheElecLrico miElectricol, miElectrico2;

a;
I

xr.*ffi

762

eaptuf,@

Herenciaypolimorfismo

--\t
, 1200,
r,Verd.e,,) ;

miCochel = new Coche O ; miCoche2 = rrew Coche ("Ford"

miElecLricol = new CocheElectrico O ; miElectrico2 = new CocheElectrico (15) ;


) )

3'

abord en el captulo 10.

da el arregio; por ejempro, 50 por ciento, La tcnica para expandi,

En el programa calculacalificacion se fij el tamao predeterminado del arreglo lista en 25' Modifique el programa de modo que el tamao del arreglo s" incr"meit" si"l archivo de entrada contiene ms de 25 estudiantes. Necesitar irn mtodo qu"

"t

""funurr-"gto ,.

4'

Extienda el programa calculacalificacion para almacenar el arreglo lista utiiizando un objeto de tipo objectoutput5tream. Proporcione a1 usuario la opcin e leer los datos desde un archivo de texto (as es com trabaja el programa original caiculacalificacion) o desde un archivo de objetos. De manera semejinte, proporcione al usuario la opcin de guardar los datos en un archivo de texto un aichivo de objetos.

5'
6"

Modifique el programa de muestra calculacalificacion para introducir los datos desde un archivo de texto utiLzando la clase Scanner envez de las clases FileReader y BufferedReader. IJse el carcter del tabulador (\t) como delimitador.
Cmo debera modificarse el programa CalculaCalificacion si la frmula para calcular la calificacin del curso es diferente para estudiantes de primer ciclo, de segundo ciclo, de tercer ciclo y estudiantes no graduados? disear cuatro Debera subclases de EstudianteNoGraduado? o bien, modificar el cuerpo de mtodo calculaCalificacionCurso de EstudianteNoGraduado? Analice los pros y los contras

de ambos enfoques.
7

'

En el ejemplo de desarrollo del captulo 5 se defini la clase TrazaFigura, que incluye un mtodo para trazar una de tres figuras posibles: un rectngulo-, un rectngulo redondo o una elipse. Modifique esta clase como una superclase de ias tres subclases Rectangle, RoundedRectangle y Ellipse. El trazado ral de una figura se reaiiza con el mtodo TrazaFigura definido en cada una de las tres subclases. Ijtilice la clase auxiliar DrawingBoard del captulo 5 y las cuatro clases definidas en este ejercicio para escribir un programa protector de pantallas que trace 10 rectngulos, 15 rectngulos redondos y 20 elipses de varios tamaos. todas las figuras dJben desplazarse de manera suave en la pantalla.

Ejere ieios de

desarroilo

IJ:*|,?:" oesarTollo,

Para resolver los siguientes ejercicios, aplique Ia metodologa de desarrollo incremental para implementar el programa. Para cada eiercicio, identifilque las tareas del programa, cree el documento de diseo con descripciones de clase y elaore el diagrama --r p1"r"ma' Fscif los pasos del desarrollo al principio. Presenie cualquier altemativa de diseo su seleccin. Asegrese deifeouar pruebas idneai al finar de cada paso ael

Ejercicios

v63

Escriba Lin prograina gestor de finanzas personal que mantenga infolmacin sobfe sus clrentas bancarias. Incorpore ias siguientes regias:

Para 1as cnentas de ahorro, puede hacer un mximo de tres retiros de dinero sin incurrir en ningn gasto. El banco carga $i.00 por cada retiro despus del tercero. Para las cuentas de cheques, ei banco carga $0.50 por cada cheque emitido (es decir, retiros) para 1os primeros 20 cheques en un mes. Despus de eso, no hay cargos.

ndo

los
ulaCa usua-

ltosos des-

Usted debe poder abrir y guardar la informacin de las cuentas en un archivo. Debe poder listar todas las transacciones de una cuenta dada o de todas las cuentas. Incluya 1os mens que considere oportunos para seleccionar las opciones soportadas por e1 programa. Considere el uso de la clase Date para registrar la fecha de las transacciones. La clase Date pertenece al paquete java.util. Por favor, consulte el manual de eferencia java.util para obtener informacin sobre esta clase. 9. Extienda el programa del directorio del captulo 10. En vez de manejar un nico tipo de Persona, incorpore tipos adicionales de pelsonas, como AmigoPersonal y SocioNegocios. Defina estas clases como una subclase de Persona. Elabore un diseo cuidadoso para decidir si la clase Persona debera sel una clase abstracta o no. 10. Considere programa para gestionar cuatro tipos de activos: aparatos electrnicos, automviies, muebies y discos compactos. Qu clase diseara para su programa? y cuatro subclaDefinira las cuatro clases sin relacin o diseara una superciase ses? Si disea una superclase, sera abstracta? 11. Implemente el programa de gestin de activos del ejercicio 10. Pennita al usuario aadir, modificar y borrar apafatos electrnicos, automvi1es, muebles y discos compactos. Permita al usuario enumerar los activos por categora y buscar un deterLtn

:ader y

4 UdI-

de se-

cuatlo
rtodo

onas inclu-ngulo

minado activo por su nmero de serie. t2" lmplemente el programa de gestin de activos del ejercicio 11 aadiendo un objeto
de EiS.
-..:

:bclaealiza
.a

:-.
:

cla-

a::
J.

:jercirs, 15
r des-

:-{
.,, .:,

13. Escriba una apiicacin que lea las temperatulas diarias de 12 meses y permita al usuario obtener estadsticas. Ofrezcapor lo menos tres opciones: media mensual de un mes, media anual y temperaturas mxima y mnima de un mes dado. Utilice un archivo de texto para almacenar las temperaturas. Cada inea del archivo debe contener las temperaturas diarias de un mes. La primera. lnea debe contenei las tempe-

raturas de los das del mes de enero; la segunda, 1as temperaturas cie los das del mes de febrero y as sucesivamente. Utilice un objeto de tipo StringTokenizer para analiza vna lnea con las temperaturas de tipo float. Como esffuctura de datos, considere 1a utilizacin de un arreglo de Mes o un arreglo bidimensional de float. Mes es una clase que usted debe definir.

.:

-ental 'ama,

lgraseo o del

También podría gustarte