You are on page 1of 83

por

David Muoz Daz

Este docume nt o est escrito para ayudar a quien lo necesite. Puedes hacer con l lo que quieras, pero siempre de forma gratuita y desinteresa da. Adems, es demasiado malo como para venderlo. Se reiran de ti :) Si quieres aportar algo a este documen to, no dudes en ponerte en contacto con el Grupo de Usuarios de Linux de la Universidad Carlos III de Madrid (gul@gul.uc3m.es ).

Gracias a: Jose Maria Chumo por sus sugerencias para mejorar este manual Fernando Cerezal por publicitarlo en su charla sobre Program acin Orientada a Objetos y Java y a los seores del GUL por mantenerlo disponible para todo el mundo

Contenido
Aqu tienes la lista de contenidos del texto. Los aparta d o s marca dos con * son slo orienta tivos y no estn amplia me nte explicados aqu, ya que no forma n parte del objetivo de este texto. Puedes encontr a r una explicacin exhaustiva de estos aparta d o s en cualquier libro de Java, adem s de las explicaciones que te dar el profesor de la asignatu r a. Bueno, en alguna s ocasiones, que debera dar. Prefacio * (que no, que es coa) Introduccin. Cultureta. peln de historia Platn y la OOP el proble ma... ... y la solucin concepto de objeto propie da d e s mto d o s concepto de clase Java por qu Java? caracteraticas generales de Java * facilidad (je je jeeee) lenguaje interp re ta d o

tamao de los program a s orientado a Internet JVM


Cmo usar el compilad or y la JVM (javac, java) El movimiento se demuestra andando defincin de una mesa propie da d e s tipos bsicos de datos * mto d o s valor de retor no par me tr o s creacin y uso de objetos creacin primer o: las referencias segun d o: new uso el opera dor punto ms sobre creacin: constr ucto r e s qu son? peculiarida de s definicin y uso breve iniciacin al polimorfis mo * mto d o s get/ set Por qu? uso Variables de clase. Modificador Static el proble ma... ... y la solucin uso de static en propie da d e s en mto d o s consta n te s

El mtodo main, arrays y a lanzar programas! por qu el mto d o main definicin del mto d o main argu me n t o s un inciso: arrays sacab el inciso nuestr o primer progra m a

Programando a lo bestia: estructuras de control


Sentencias condicionales sentencia if expresin lgica bloque de sente ncias compa r a d o r e s de magnitu d AND, OR, NOT compa r a d o r e s de cadenas ifs anida dos if sin elses: CUIDADO! solucin rara solucin ms rara sentencia switch uso break comer te el coco 4 Sentencias repetitivas definicin sentencia while regla general para el uso de bucles variacin do - while sentencia for While o for?

Recursividad definicin metodologa: la cola del cine partes de un mtodo recursivo los factoriales
Herencia para qu sirve cmo se usa: exten d s redefinicin de mto d o s uso de super()

una nota bastante importante


Casting prelu dio al casting: las referencias la seora referencia cmo funciona compa r aci n de referencias Arreglan d o bicicletas: par me tr os que son referencias casting Por qu? cmo se usa resu me n comer te el coco 6 upcasting, downcasting, Y siguiendo con el ingls, explicit and implicit cast upcasting downcasting casting implcito casting explcito

La Clase Object

definicin
contenid o *

para qu ese contenido? la gran utilidad de la clase Object: referencias de tipo Object Interfaces definicin uso bsico de interfaces uso avanzado de interfaces: referencias de tipo de interfaces herencia?Interfaces?comorl? Eplogo

El contenido de este texto es el estrictamente necesario para poder abordar cualquier problema de Programacin. Este texto es, por tanto, la base necesaria para poder enfrentarnos a las asignatur as de Programacin y Laboratorio de Programacin. En este texto no vamos a ver deter mina dos temas, como Applets, paquetes, pruebas de programas, etc. Para cualquier consulta sobre dichos temas, te recomiendo los libros de Java de la editorial Sun o alguno de la infinidad de manuales gratuitos que hay por la red. Por tanto, es necesario que te conciencies de que leer este texto no implica aprobar: implica ser capaz de aprobar. Si te sirve de algo, cuando yo llegu a primero, saba bastante menos de lo que hay aqu escrito.

Prefacio No te engaes: tenemos mucha labor por delante. Pero no hay que pensar que es ardua y temible. En absoluto. O al menos, espero que no lo sea para ti. Programar implica siempre dos cosas: Primero, hay que comerse el coco bastante, pero no para alcanzar complejos conceptos (bueno, para esto tambin), sino para todo lo contrario: para conseguir poner nuestro pensamiento a la altura de un cacho de silicio, que no parece muy listo.... Segundo, la curiosidad no mata al gato, sino que curiosity

Skilled the cat

(por cierto, n.p.i. de de quin es esta frase. Se la he copiado a un miembro del GUL. As que si esta frase es suya, le pido diculpas por no pagar derechos de autor) O sea, que siempre, repito, siempre es bueno parar de estudiar y encender el ordenador para hacer alguna prueba de lo que estemos estudian do. Si vemos casting ser muy positivo que mandes a tomar por saco los apuntes y escribas un par de clases para probar el acceso a los miembros de una calse va una referencia de tipo la superclase. Parece mentira, pero esta frase tiene sentido. En serio, nunca vas a aprender a programar con un libro, siempre lo aprenders por tu cuenta. As que vete haciendo a la idea de que vas a pasar muncho rato delante de la pantalla, aunque espero que no sea demasiado tiempo. O que al menos no sea tedioso. He intentado explicar todo este rollo usando ejemplos de la vida real. Tal vez quede un poco asquerosa m e nte pedante explicar las clases metiendo a Platn por medio, pero creo que hacindolo vamos a entender los conceptos ms fcilmente, y sobre todo, no se van a olvidar. Por supuesto, no creas que todo es Platn, tambin hablaremos de tu vecina, de la mesa Margarita, de pginas gu, la bicicleta Anacleta, y de mil cosas ms. Bueno, mil... lo que se dice mil.... Por supuesto, todo ello respaldado por el pez Otilio, el pato Onorato y el pjaro que no s cmo demonios se llama, que no son ms que excusas para apartar un poco la atencin y hacer la lectura un peln ms agradable. Espero haber logrado, aunque slo sea en pequea parte, estos objetivos. Ahora, como dice la historia de la sopa de piedra, debes poner t de tu parte. nimo!

Introduccin. Cultureta. Normalmente, para empezar se opta por definir qu es programar, cmo se lleva a cabo, conceptos como software, hardware, memoria, etc etc etc. Vamos a ignorar todo este rollo porque realmente no importa en absoluto. Nosotros, por ahora, no nos vamos a preocupar de la Yo soy un programa do r capacidad de la memoria o de la leche. de la velocidad del proce sador. A nosotros nos interesa programar. Cuando aprende m os a programar siempre se nos plantea si debemos compaginar la progra macin con el lenguaje de programacin. Parece una tontera, pero podemos aprender OOP sin saber ningn lenguaje. Es cierto: podemos saber sobre clases, objetos, herencia, casting, etc sin saber una maldita palabra de ningn lenguaje. Sin embargo, siempre es positivo compaginar nuestro aprendizaje de programacin con el de un lenguaje propicio para ello. Adems de la OOP, y a modo de curiosidad (cultureta), existen otros tipos de programacin, cada uno con un lenguaje de programacin tpico. Esta parte, si quieres, te la puedes saltar. La programacin lineal tiene como fundador el antiguo BASIC. A lo largo de los aos, el BASIC ha ido cambiando hasta que hoy en da existen compiladores de BASIC orientado a objetos (Visual Basic, por ejemplo, mantiene una filosofa de OOP). La programacin lineal se daba con los primeros intrpretes de BASIC. Aqu hay un ejemplo de este lenguaje:
10 20 30 40 INPUT Cmo te llamas?, NOMBRE$ SALUDO$ = Hola +NOMBRE$+ PRINT SALUDO$ END

Ves? El programa empieza en un punto, y acaba en otro. Esto, claro, tiene sus inconvenientes: no podemos hacer repeticiones, ni nada de eso. Nacieron las sentencias condicionales:
10 20 30 40 50 60 70 INPUT Cmo ests?,COMO$ IF COMO$=bien GOTO 50 IF COMO$=mal GOTO 70 GOTO 10 PRINT Vaya, me alegro. GOTO 80 PRINT Algrate!

80 END

El siguiente paso es la programacin procedimental: consiste en dividir el cdigo en fragmentos independientes. Lenguaje tpico, el Pascal.
var cad:String; procedure debuti; begin Writeln('me alegro'); end; procedure notandebuti; begin Writeln('alegrate!'); end; begin Writeln('Cmo ests?'); readln(cad); if (cad='bien') then debuti else notandebuti; end.

Hay muchos ms tipos de programacin, y tambin muchos otros lenguajes muy raros, Smalltalk, ADA, Prolog.... En realidad, hoy en da muchos de estos lenguajes se usan con fines didcticos o experimentales. A nosotros nos interesa la Programacin Orientada a Objetos (OOP, de Object - Oriented Program ming). Se basa en encapsular fragmentos de cdigo en burbujas independientes entre s. Los cdigos mostrados antes no tienen sentido en OOP. Vamos a ver por qu. Platn y la OOP La pregunta es las siguiente: Tenemos una mesa en la cocina, una en el saln, una mesilla de noche y una en un taller. Estas mesas son diferentes entre s, pero, sin embargo, hay algo en ellas que hace que todas SEAN mesas. Una es cuadrada, otra redonda, unas con tres patas y otras con cuatro. Por qu, si son tan diferentes, son todas mesas? Este hombre de aqu dijo que haba un mundo aparte del nuestro en el que existan unos seres perfectos, inmutables, universales, etc etc etc, a quienes llam Ideas. Los seres de nuestro mundo fsico seran copias imperfectas de estas Ideas. Imagina por tanto que todos los objetos que tenemos alrededor son copias de las Ideas. De esta forma, al ser copias imperfectas, no seran iguales entre s, pero seguiran teniendo esa esencia comn. Esta teora sirve para explicar la realidad y dar un poco de cabida a la ciencia. Si la ciencia trata sobre las cosas globales, es

decir, los hechos universales, no los especficos, entonces tiene que haber algo universal. Bueno, pues nuestra intencin es semejante: vamos a tratar de explicar, no la realidad, sino los problemas que nos encontram o s, que de una forma u otra, son parte de la realidad. o no? En OOP definimos un concepto ms que fundame ntal: el concepto de objeto . Un objeto es un conjunto de: a) Datos b) Mtodos Supongamos dos objetos semejantes, por ejemplo, dos mesas. Datos que pueden concernir a las mesas, por ejemplo, son su color, nmero de patas, su forma, etc. As, si tenemos dos objetos mesa, cada uno con datos diferentes, tenemos dos mesas diferentes, que es lo que planteba mo s al principio: dos objetos de la misma naturaleza (mesa), pero diferentes entre s. A Platn esto le habra encantado! Debido a que los datos de un objeto definen en parte este objeto (lo diferencian de los dems), a veces llamamos a estos datos Propiedades . Se te ocurre algn mtodo propio de una mesa? A m no, las mesas son objetos puramente pasivos, ellas mismas no hacen nada. Sin embargo, vamos a suponer que el cambio de color es una accin propia de la mesa (y no del pintor). De acuerdo, ya tenemos el diseo de nuestra mesa. Ya conocemos el concepto de objeto . Vamos a seguir con el seor Platn. Cmo un carpintero puede crear una mesa? Segn este griego, su alma, antes de nacer, vislumbr las Ideas, y durante la vida de la persona, el alma recuerda algunas de estas Ideas (aunque no todas....) As, un carpintero recuerda haber visto la Idea de Mesa, y por ello sabe hacer mesas. Es decir, el carpintero se FIJA en la Idea de Mesa para crear una mesa. Si ya conocemos lo que es un Objeto, Qu es una Idea? Pues, sencillamente, la definicin de ese objeto, que, por cierto, nosotros llamamos clases . Platn dice que los objetos fsicos son copias de las Ideas. Nosotros decimos que los objetos con instancias de las clases.

Para Platn, los objetos son copias de seres universales llamados Ideas. Las son, por tanto, la definicin de los objetos fsicos, aunque stos pueden ser diferentes entre s. Para la OOP, los Objetos son instancias de unas definiciones generales que llamamos Clases. Dos objetos con propiedades diferentes (dos mesas con diferente color) siguen siendo instancias de la misma clase (la clase mesa).

unos Ideas

stos son los conceptos funda ment ales de la OOP. Es estrictamente necesario compren derlos a fondo antes de seguir adelante. Prate un momento a pensar si entiendes a fondo... OBJETO CLASE PROPIEDADES MTODOS INSTANCIA Cuidado! Si decimos que dos objetos de la misma clase tienen las mismas propiedades, tal vez lo que realmente queramos decir es que dos objetos de la misma clase tienen EL MISMO VALOR PARA TODAS Y CADA UNA.DE SUS PROPIEDADES. Es evidente que dos objetos de la misma clase van a tener las mismas propiedades: dos mesas tendrn color, forma, nmero de patas, etc. Pero tal vez digamos que dos mesas tienen las mismas propiedades cuando queremos decir que ambas mesas tienen la misma forma, el mismo color y el mismo nmero de patas. Hay que tener cuidado con esto, aunque tampoco es tan importante. Para comerse el coco.... (1) Tenemos dos objetos de la misma clase, con exactamente las mismas propieda des Son el mismo objeto? Java Java es un lenguaje de programacin. La verdad es que no va a recibir ningn premio por este simple hecho. Sin embargo, s va a recibir cierta atencin por nuestra parte, porque, sencillamente, es la herramienta que nosotros vamos a utilizar. Que quede muy claro, Java es un MEDIO para programar en OOP. Podemos programar en OOP con otros muchos lenguajes, Delphi, Visual Basic, o C++.

Java naci con una intencin muy clara: hacer la vida ms fcil al programa do r. C+ + es el lenguaje ms potente que existe ahora mismo. Pero tiene un grave problema: es lo ms complicado que hay. Un ejemplo:
#include <owl.h> // Define la clase derivada de TApplication class THelloApp : public TApplication { public: THelloApp(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) : TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {}; virtual void InitMainWindow(); };

// el MainWindow de la clase void THelloApp::InitMainWindow() { MainWindow = new TWindow(NULL, "Hola Mundo"); } int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { THelloApp HelloApp ("HelloApp", hInstance, hPrevInstance, lpCmdLine, nCmdShow); HelloApp.Run(); return HelloApp.Status; }

Bueno, pues este fragmento de cdigo abre una ventana con el ttulo Hola Mundo!. Visto lo visto, Java trata de hacer la vida un poco ms fcil. Adems, un programa en Java ocupa bastante poco espacio en disco, mientras que uno en C++ ocupa todo lo que quieras y un poco ms. As que, gracias a eso, Java es tambin propicio para aplicaciones que corran por Internet y esas cosas. Pero todo eso ya lo veremos.

Java NO lo entiende directamente el procesador. Java es un lenguaje INTERPRETADO, es decir, que se traduce para que el procesador pueda entenderlo. C++, una vez compilado, es entendido perfectamente por el procesad or, mientras que Java no. Java se compila y se generan los bytecodes, que es otro lenguaje mucho ms sencillo, pero el procesador sigue sin entenderlo. Para ello, los bytecodes tienen que INTERPRETARSE por la Java Virtual Machine (JVM), que, en realidad, es otro programa (escrito, por cierto, en C++) que sabe interpretar los bytecodes. Bueno, esto es un poco extrao, pero en realidad es muy fcil. Al escribir un programa en C+ +, por ejemplo, se compila y funciona solito. Pero al escribirlo en Java, se compila y necesita otro programa que lo haga funcionar. Este otro programa se llama JVM. Ya est. No es tan mortal, no? Ventajas de Java sobre los lenguajes no interpreta dos? muchas, por ejemplo, seguridad: Si un programa en Java intenta hacernos la pueta, la JVM lo detendr , mientras que el procesador no podr detener nunca un virus escrito en C++. Otra ventaja es el ya mencionado reducido tamao de los programas en Java. Otra, mucho ms importante, un programa en Java funciona en Windows, en Linux, en Mac, en Solaris, etc, porque lo que cambia es la JVM. Aqu no vamos a extender nos en el funcionamiento de los compiladores de Java y las JVM. Sin embargo, vamos a recordar un poco el proceso. 1.- Creamos el archivo xxxx.java 2.- lo compilamos con javac xxxx.java 3.- lo ejecutam os con java xxxx El paso 3 es el que invoca a la JVM. Ms explicaciones, ayuda en lnea. Antes de seguir adelante, vamos a pararnos recapacitar sobre si has entendido los conceptos de: un poco para

LENGUAJE plantear me LENGUAJE INTERPRETADO programar.... Y COMPILADO COMPILADOR JVM BYTECODES Para comerse el coco......(2) Teniendo en cuenta que la JVM es un programa escrito en un lenguaje

Empiezo a esto de

compilado, puede ser entendido por la propia JVM? El movimiento se demuestra andando. Vamos a escribir un pequeo programa en Java. Su fin? definir las mesas que tanto tiempo nos han acompa ad o. Recordemos la CLASE MESA: Propiedades: color, nmero de patas, forma Mtodos: cambiar el color Bueno, vamos a pensar un poco. Como sabrs, los nombres o IDENTIFICADORES en Java son una cadena de caracteres que almacenan un valor determinado, o el nombre de un mtodo, o el nombre de una clase, o yo qu s. Tenemos que tratar de inventarnos identificadores con nombres sencillos, que no sean rebuscados, sin caracteres raros. A m se me ocurren los siguientes: para para para para el el la el color, pues color nmero de patas, numPatas forma, pues forma mtodo que cambia el color, pues cambiarColor

Definicin de propiedade s Vamos a centrarnos en las propiedades, y luego veremos los mtodos. Seguimos pensando. El color ser una cadena de caracteres (marrn, violeta, joer, una mesa violeta...), que en Java se denomina String, al igual que la forma (Redonda, cuadrada). El nmero de patas ser un nmero entero, que se llama int. La definicin de la clase Mesa.java empezara as: class Mesa { String color; int numPatas; String forma; . . . Esto ya tenemos que ser capaces de entenderlo bien. Una mesa tiene un color, un nmero de patas y una forma. El nmero de patas es

un nmero entero, mientras que la forma y el color son cadenas de caracteres. Bueno, pues as se han definido. Ahora no ha lugar a pensar cmo se define el color de una mesa determina da, o su forma, o cmo saber qu color tiene otra mesa cualquiera..... todo eso ya lo veremos. Ahora estamos DEFINIENDO la clase Mesa, no hacemos nada ms. En cualquier libro encontrars los tipos bsicos de variables y sus rangos de valores. Tendrs que aprendrtelos, aunque slo para el examen. Luego, puedes olvidarlos. Bsicamente son int, short, long, double, float, char, String y boolean. Este es un buen momento para aprenderte los tipos de datos bsicos. Definicin de mtodos ya te los has aprendido? Bien! Vamos a por el mtodo cambiarColor. Un mtodo consta, aparte de su nombre (o IDENTIFICADOR), claro est, de

a) valor de retorno. b) parmetros Un mtodo puede devolver un valor, o puede no hacerlo. Por ejemplo, un mtodo que calcule la suma de dos nmeros debera devolver otro nmero, o un mtodo que abra un fichero del disco debe devolver si ha podido abrirlo o no. Ahora bien, hay mtodos que no tienen por qu devolver nada. Por ejemplo, un mtodo que muestre un saludo en pantalla no tiene por qu devolver nada. A la hora de definir el tipo de dato que devuelve un mtodo, se antepo ne al nombre de ese tipo de dato (int, float, boolean, String....) al nombre del mtodo. Por ejemplo: int calculaSuma() float raizCuadrada() boolean abrirArchivo() / / devuelve un entero / / devuelve un real / / devuelve un valor lgico

Los mtodos que no devuelven nada se declaran como void: void saludo() / / no devuelve nada

Bien. Vayamos ahora a por los parmetr os. Un mtodo que calcule 5*4 est claro que no va a necesitar parmetr os, porque el mtodo no puede hacer nada ms que calcular 5*4. Sin embargo, un mtodo que calcule la multiplicacin de dos enteros cualquiera necesitar conocer esos enteros, es decir, se los daremos como parmetro. Es como si queremos saber dnde est determinada calle, y le pregunta m os a alguien: tenemos que decirle qu calle buscamos. Imagnate, Disculpe, podra decirme dnde est la calle? No tiene sentido, habra que preguntar Disculpe (educacin ante todo), podra decirme dnde est la calle Butarque?. Bueno, pues como ste se te pueden ocurrir mil ejemplos

Es MUY IMPORTANTE que diferencies cundo un mtodo necesita parmetros y cundo no.

Una cosa s es cierta: no hay una regla general para saber si un mtodo necesita parmetros, para saberlo necesitamos la mplementacin del cdigo, y el sentido comn. Vamos a ver unos ejemplos: int suma(int a, int b) recibe un entero a y un entero b y devuelve otro entero String concatenar(String a, String b) recibe dos cadenas de caracteres y devuelve otra cadena de caracteres float raizCuadrada(int a) recibe un entero y devuelve un real Debe quedar MUY MUY MUY claro este rollo de los parmetr os y del tipo de dato devuelto por un mtodo. Vamos a ver los mtodos

anteriores implementa dos y comenta dos para que se vea todo mucho mejor, y ya de paso aprendem o s cmo hace un mtodo para devolver un valor usando return: int suma(int a, int b){ return a+b; } Este mtodo recibe dos enteros, a y b, y devuelve su suma, que ser otro entero. Si hacemos en cualquier parte del programa int numero = suma(3,5); estamos diciendo que el entero numero va a valer lo que devuelva el mtodo suma pasndole como parmetr os 3 y 5. suma devolver 3+5, y entonces numero pasar a valer 3+5. String concatenar(String a, String b){ return a+ +b; / / las comillas encierran un espacio en blanco } Recibe dos cadenas y las concatena poniendo un espacio en blanco entre medias. Fjate en la diferencia entre usar + con nmeros y usarlo con cadenas. Si en cualquier punto del programa escribimos String cad = concatenar(Hola,Mundo); estamos diciendo que la cadena (String) cad va a valer el resultado que concatenar devuelva pasndole como argumentos las cadenas Hola y Mundo; Como concatenar coge las dos cadenas que hemos pasado como parmetros (Hola y Mundo) y las devuelve juntas con un espacio entre medias (devuelve Hola Mundo), la cadena cad pasar a valer Hola Mundo void saludo(){ System.out.println(Holas!); } este mtodo no tiene parmetros, y no devuelve nada de nada. As, se le invocar en cualquier parte del programa: saludo(); y ya est. Como en el mtodo no hay definidos parmetros, pues no le pasamos parmetr os, y como el mtodo no devuelve nada, pues es ilcito escribir algo como: int resultado = saludo(); / / mal!!!!!

porque saludo() no devuelve nada (recuerda: se ha definido como void y no se ha escrito ningn return), y como no devuelve nada, Java no sabe qu valor meter en resultado. Bueno, pues este es el funcionamiento de un mtodo. A modo de resu men, cuando un mtodo es invocado, puede necesitar o no parmetros. Que los necesite o no depende de cmo hemos definido dicho mtodo, es decir, si hemos definido variables entre los parntesis del mtodo: ... metodo(parametro1, parametro2, ....) int suma(int a, int b) o si no las hemos definido: ... metodo() por ejemplo: void saludo() Un mtodo puede devolver un valor, o bien puede no devolver nada. Depende de cmo hemos definido el mtodo: si lo definimos como void: void saludo() entonces no devuelve nada, pero si lo definimos de otra forma: int suma(....) entonces devolver un dato de un tipo determina do (int, float...), y ser OBLIGATORIO escribir un return en el cuerpo del mtodo. int suma(int a, int b){ int resultado = a+b; } Este mtodo es casi igual al que hemos visto poco ms arriba, peeeeeeeeeero tiene un grave problema: hemos dicho que devuelve un entero ( INT suma(int a, int b) ), pero no hay ningn return en el cuerpo del mtodo. Habr un error de compilacin! Una cosa ms, que un mtodo devuelva algn valor NO IMPLICA (curiosamente) que haya alguna variable que reeciba dicho valor. Es decir, las siguientes lneas son perfectamente legales: int resultado = suma(5,3); . . . suma(5,3); por ejemplo:

La nica pega es que la segunda lnea llama al mtodo suma, le pasa sus parmetr os pertinentes, pero nadie recibe el resultado. Esto, parece una chorrada, pero es til. Supongam os que tenemos un mtodo: boolean abrirFichero(String nombreFichero) cuya tarea es abrir un fichero determinado. Este mtodo devuelve un boolean que indica si se ha abierto el fichero con xito. Bien, puede que en algn momento hagamos: boolean hemosPodido = abrirFichero(miFichero.txt); para saber si hemos podido abrir el fichero. Esto sera lo ms normal, pero en algunas ocasiones no necesitamos saber si se ha abierto exitosamente, porque sabemos que va a ser as, por ejemplo, al hacer algn programilla tonto en nuestra casa. Si no necesitamos asegurar nos de si el fichero se ha abierto o no, entonces podemos hacer abrirFichero(miFichero.txt); e ignoramos el valor que abrirFichero devuelve. Bueno, pues esto es todo sobre los mtodos! Antes de seguir adelante, como siempre, asegrate de haber entendido bien los conceptos de: PROPIEDAD MTODO TIPO DE DATOS (int, float....) PARMETROS VALOR DE RETORNO DE UN MTODO SENTENCIA RETURN VOID Recuerda siempre que un valor de retorno puede ser ignorado Ejercicio Una vez hayas entendido perfectamente todo este rollo, puedes escribir la definicin completa de la clase Mesa. Plantate qu parmetr os le pasaramos al mtodo cambiarColor() y qu valor devolvera. Vamos! Solucin A m se me ocurre que cambiarColor() tendra como parmetr os una nica String, y no devolvera nada. El resto de la clase ya lo hemos definido.

class Mesa { String color; int numPatas; String forma; void cambiarColor(String nuevoColor){ color = nuevoColor; bueno... } }

Empieza lo

Creacin y uso de objetos Ya tenemos definida la clase Mesa. Ahora quiero crear una mesa. Cmo se hace eso?... primero: las referencias Cuando creemos un objeto, la JVM genera una burbujita que es nuestro objeto. Claro, que para que ese objeto haga cosas necesitamos llamarlo de alguna forma. Si quieres que, en medio de una fiesta atestada de gente tu amigo Miguel te diga, por ejemplo, la hora, como digas Dime la hora!, no te van a hacer ni caso, porque cada uno pensar (si te ha odo) que no le ests llamando a l. Tendrs que decir Miguel, dime la hora!, para que el seor Miguel te haga caso. En definitiva, que si vas dando gritos por la calle ni Dios te va a hacer caso, mientras que si a cada frase le antepones el nombre de la persona a la que imperas, pues ya te puede atender. En Java esto es exactamente igual, a cada objeto se le debe dar un nombre para poder llamarle de alguna forma cuando le necesites. Bien, pues a estos nombres se les denomina Referencias . Si yo creo dos mesas y quiero cambiar el color de una sla, Cmo le digo a la JVM a qu mesa quiero cambiar el color? Pues fcil, si creo dos mesas, a una la llamo Margarita y a la otra Alberto, y luego digo que cambie el color de Margarita. segundo: el operador new newsignifica nuevo. Y este es un ejemplo de otra cosa que por este simple hecho no va a recibir ningn premio. new sirve para a) crear un nuevo objeto b) definir la REFERENCIA a ese nuevo objeto. Cmo se usa? Pues muy fcil:

CLASE REFERENCIA = new CLASE();

por ejemplo: Mesa Margarita = new Mesa(); Mesa Alberto = new Mesa(); por ahora, olvida los parntesis de new CLASE()

Por qu esos parntesis en new Mesa()? Por ahora, haz caso al pez. Pues ya sabemos definir objetos e incluso crearlos! Ahora, vamos a aprender a utilizarlos. Supongamos que quiero crear dos mesas, Margarita y Alberto, y quiero cambiar el color de la mesa Margarita. Tendr que llamar al mtodo cambiarColor() de la mesa Margarita. Cmo se hace esto? Pues usando algo tan tonto y tan simple como un punto: Mesa Margarita = new Mesa(); Mesa Alberto = new Mesa(); Margarita.cambiarColor(Rojo); Quiero cambiar el color de la mesa Alberto? Alberto.cambiarColor(Azul); Ya est. Hala. Pareca complicado todo esto? Pues ya ves qu complicacin ms grande. Ya sabemos definir objetos, crearlos y usar sus mtodos. Para que te convenzas, aqu tienes un cachito de mi prctica de Junio:
log.write(" log.write(" log.write(" log.write(" tipoReserva horaInicio horaFin fecha = = = = "+r.getTipoReserva()); "+r.getHoraInicio()); "+r.getHoraFin()); "+r.getStringFecha();

Sabiendo que log y r son objetos, Hay algo complicado? Hay algo que no entiendas? Claro que no! Constructores

A primera vista, parece que new es un CONSTRUCTOR, porque su misin es construir nuevos objetos. Bueno, pues nooooop. new INVOCA a un constructor, NO ES un constructor. Bueno, no es tan difcil. new invoca a un constructor. Vale. Y qu es un constructor? Un constructor es un mtodo especial, propio de cada clase. Su funcin es INICIALIZAR el contenido, las propiedades, el estado, etc etc del objeto. Podemos hacer que cuando creemos una mesa cualquiera, comience siendo cuadrada de cuatro patas y azul. Pero eso lo veremos luego. Por qu el constr uctor es especial? Por varias razones: Primero : se invoca UNA VEZ para cada objeto. Los mtodos de un objeto se pueden llamar todas las veces que quieras: Margarita.cambiarColor(rojo); / / y acto seguido.... Margarita.cambiarColor(azul); / / y otra vez... Margarita.cambiarColor(verde); Sin embargo, el constructor va a ser invocado una sla vez, cuando lo diga new. Segundo : nunca devolver ningn valor Tercero : sin embargo, no se define como void. Recuerda que cuando un mtodo no devuelve ningn valor, se define como void. Bueno, pues el constructor no. Cuarto : su nombre es el mismo nombre de la clase a la que pertenece. No puedes escoger el nombre del constructor. Recuerdas los parntesis a los que se refera el pez? Mesa Margarita = new Mesa(); Por qu estos parntesis? Pues est ya claro: Mesa() es el nombre de un mtodo, el CONSTRUCTOR, y por eso lleva parntesis. Bueno, pues una vez dicho esto, vamos a cambiar un poco lo que decamos sobre el uso de new, y vamos a cambiarlo por: CLASE REFERENCIA = new CONSTRUCTOR(); Antes de seguir, asegrate de entender bien los conceptos de REFERENCIA OPERADOR PUNTO . NEW

CONSTRUCTOR Definicin de constructores Vamos a definir un constructor para la clase Mesa. Nuestra intencin, hacer que cada mesa nueva sea cuadrada, azul y con cuatro patas. Bueno, pues es muy fcil, aadimos a la clase el mtodo en negrita:

class Mesa { String color; int numPatas; String RECUERDA: el constructor tiene el void cambiarColor(String nuevoColor){ clase, color = nuevoColor; valor, } void Mesa() { color = azul; numPatas = 4; forma = cuadrada; } } Ahora, cuando hagamos Mesa Margarita = new Mesa(); Margarita ser una mesa cuadrada azul de cuatro patas, Una mesa en condiciones, vaya! Pero hay un problema: yo no quiero mil mesas iguales. Yo quiero crear una mesa como a m me d la gana, yo no quiero que todas las mesas sean azules y cuadradas con cuatro patas. Se te ocurre algo para solucionar esto? Podemos definir un constr uctor con parmetr os! As, cuando creemos una mesa le daremos su color, su nmero de patas y su forma iniciales. A ver, sera algo as: Mesa(String colorInicial, int formaInicial){ color = colorInicial; numPatas = numPatasInicial; numPatasInicial, String y se define sin no devuelve ningn mismo nombre que su forma;

forma = formaInicial; } Esto es genial. Ahora podemos hacer: Mesa Margarita = new Mesa(rojo, 4, redonda); Mesa Catalina = new Mesa(verde, 3, triangular); Hala. Qu constructor te gusta ms? Podemos prescindir de uno de ellos. Aunque, gracias a algo que llamaremos Polimorfism o , podemos quedar nos con los dos constructores A LA VEZ. (Vaya! dos constructores diferentes!)

El Polimorfismo permite tener varios mtodos diferentes entre s y con el mismo nombre. Un buen momento para echarle un vistazo!

Si te digo la verdad, yo pocas veces uso los constructores con parmetros (que no significa que sean malos, eh? no te creas......). En su lugar, utilizo los.....

Mtodos get / s et Cuando no definimos un constr uctor en una clase, al invocar new la JVM usar el CONSTRUCTOR POR DEFECTO, que inicializa las propiedades del objeto con ceros, referencias nulas, etc (que lo de referencias nulas no te asuste! ya lo veremos). Para inicializar las propiedades usamos un constructor personalizado, propio, caracterstico, o como lo quieras llamar. Estupendo. supn que en medio del programa quiero cambiar UNA SOLA propiedad de un objeto. En nuestro caso, puedo cambiar el color. Pero imagina que tengo una mesa roja:

Mesa Margarita = new Mesa(rojo, 4, redonda); Y quiero hacer que sea amarilla. Bueno, pues tengo dos opciones: primera : crear una nueva mesa, casi igual: Mesa Margarita = new Mesa(amarillo, 4, redonda); (Esto parece guai, pero te aseguro que no siempre va a resultar fcil) segunda : definir una serie de mtodos que cambien UNA SOLA propiedad del objeto. A este tipo de mtodos se les denomina mtodos set, porque suelen comenzar con la palabra set (poner): Vamos a definir tres nuevos mtodos para nuestra clase Mesa:

void setColor(String nuevoColor){ color = nuevoColor; } void setForma(String nuevaForma){ forma = nuevaForma; } void setNumPatas(int nuevoNu mPatas){ numPatas = nuevoNu mPatas; } Fjate t qu cosas, oche. Ahora resulta que setColor y cambiarColor hacen exactamente lo mismo. Prescindiremos de uno de ellos. Por ejemplo, de cambiarColor. Est bien esto, eh? Bueno, tmate un respiro, y vamos a por los mtodos get. Su funcin es obtener (get) el valor de una propiedad determinada. No es difcil adivinar que todo mtodo get se definir con algn tipo de dato de retorno (int, String...) y que adems tendr un return. Normalmente los mtodos get no tendrn parmetr os. Recuerdas todo eso? Si no, ya sabes.... Vamos a definir los mtodos get de nuestra clase Mesa. Empecemos con el color. Llamaremos al mtodo getColor. Ya que el color es una String, getColor devolver una String: String getColor(){

return color; } De forma semejante haremos con getForma: String getFoma(){ return forma; } getNumPatas devolver un valor entero: int getNumPatas(){ return numPatas; } Bueno, pues resumimos nuestra clase Mesa; tres propiedades, tres mtodos set para definir esas propiedades, tres mtodos get para obtener el valor de las propiedades, un constr uctor con parmeros y otro sin parmetr os, y pasamos del mtodo cambiarColor. La clase Mesa est escrita en la siguiente pgina. Aqu no cabe....

class Mesa { String color; int numPatas; String forma; void setColor(String nuevoColor){ color = nuevoColor; } void setNumPatas(int nuevoNu mPatas){ numPatas = nuevoNu mPatas; } void setForma(String nuevaForma){ forma = nuevaForma; } String getColor(){ return color; } String getForma(){ return forma; } int getNumPatas(){ return numPatas; } Mesa(String colorInicial, int numPatasInicial, formaInicial){ color = colorInicial; numPatas = numPatasInicial; forma = formaInicial; } Mesa() { color = azul; numPatas = 4; forma = cuadrada; } } String

Variables de clase. Modificador static. Supn que tenemos una empresa que publica pginas web en Internet para otras compaas. Supn que, como empresa que somos, en

cada pgina queremos anunciar nuestros servicios, por ejemplo, poniendo nuestro nmero de telfono. As, cada vez que alguien visitase la pgina de uno de nuestros clientes sabra cul es nuestro telfono para as poder contratar nuestros servicios. Hasta aqu bien, verdad? Vale. Supn que tenemos una clase paginaGu con las propiedades direccin , contenido y numeroTelfon o . Cada vez que creemos una pgina, le daremos un contenido, una direccin y nuestro nmero de telfono. Por supuesto definimos en la clase todos los mtodos set y get necesarios. Creo que eres Ahora supn que cambiamos nuestra sede y, por tanto, totalmente capaz de nuestro nmero de telfono. escribir la clase pagi naGu Dios! Hemos creado mil pginas web y ahora tenemos que cambiar el nmero de telfono de todas! Mil llamadas al mtodo setNumeroTelfon o ! Pues no, si hacemos que todos los objetos de la clase paginaGu compartan la propiedad numeroTelfono. As, si cambiamos el nmero de telfono de una sola pgina, cambiar el de todas las dems pginas. Guai. Creo que este ejemplo es muy ilustrativo, verdad? Bueno, pues pasemos a la accin. En Java, una propiedad que se comparte por todos los objetos de una clase se llama variable (propiedad) de clase o esttica. Por qu? La primera denominacin hace referencia a que podemos entender que una variable compartida NO pertenece a los propios objetos, sino slo a su clase. Es como si las Ideas de Platn definiesen no slo las propiedades y el comporta miento de los objetos fsicos, sino que adems definiesen el contenido de alguna propiedad. Si todas las mesas fuesen de madera, la propiedad material de una mesa estara definida en la Idea de mesa, no en cada mesa. Bueno, pues es slo una idea. Respecto al otro nombre, variable esttica, ste viene dado porque en Java, para definir una variable compartida se le antepone el modificados static : static int numeroTelfon o; Hala. Pues ya est. Aadiendo un static antes de una propiedad hacemos que esa propiedad sea compartida por todos los objetos.

Supn ahora que queremos saber cuntas mesas hemos fabricado. Bueno, pues vamos a aadir una propiedad esttica numMesasFabricadas a la clase Mesa. Inicialmente, numMesasFabricadas valdr cero, pero cada vez que un constructor sea invocado, aumentar en una unidad. Despus definiremos un mtodo getNumMesasFabricadas() para saber cuntas mesas llevaremos creadas. Bueno, pues la clase Mesa quedara definida asn (de nuevo, en una hoja aparte):

class Mesa { String color; int numPatas; String forma; static int numMesasFabricadas = 0; void setColor(String nuevoColor){ color = nuevoColor; } void setNumPatas(int nuevoNumPatas){ numPatas = nuevoNumPatas; } void setForma(String nuevaForma){ forma = nuevaForma; } String getColor(){ return color; } String getForma(){ return forma; } int getNumPatas(){ return numPatas; } Mesa(String colorInicial, int numPatasInicial, String formaInicial){ color = colorInicial; numPatas = numPatasInicial; forma = formaInicial; numMesasFabricadas = numMesasFabricadas + 1; } Mesa() { color = azul; numPatas = 4; forma = cuadrada; numMesasFabricadas = numMesasFabricadas + 1; } int getNumMesasFabricadas() { return numMesasFabricadas; } }

Y ya est. Ahora, si hacemos: Mesa Margarita = new Mesa(Azul, 3, redonda); int num1 = Margarita.getNumMesasFabricadas(); Mesa Catalina = new Mesa(Verde, 4, triangular); int num2 = Catalina.getNumMesasFabricadas(); int num3 = Margarita.getNumMesasFabricadas(); Cunto valdrn num1 , num2 y num3 ? Pues, respectivamente, 1, 2 y 2. Tal vez te hagas la preguna siguiente: si podemos definir propiedades compartidas, Podemos hacer lo mismo con los mtodos? Tiene sentido definir un mtodo compartido? Cmo se hace? Una existencia divergente implica un universo divergente? Bueno, pues s se puede definir un mtodo esttico, y s que tiene sentido. Adems, se hace igual que con las propiedades, anteponiendo un static a la definicin del mtodo. Lo de la existencia lo dejamos para otro momento. Por ejemplo, podemos saber cul es el nmero de mesas fabricadas sin necesidad de preguntr selo a una mesa determinada. Podemos preguntar a la propia clase Mesa! Cambiamos el mtodo: static int getNumMesasFabricadas() { return numMesasFabricadas; } y ahora podemos hacer: Mesa Margarita = new Mesa(Azul, 3, redonda); int num1 = Mesa .getNumMesasFabricadas(); Mesa Catalina = new Mesa(Verde, 4, triangular); int num2 = Mesa .getNumMesasFabricadas(); int num3 = Mesa .getNumMesasFabricadas(); Fjate que la llamada a getNumMesasFabricadas() la hacemos sobre Mesa y no sobre un objeto determinado. Bueno, ste hecho no debe traerte de cabeza nunca de los jamses, de verdad! los mtodos y las variables estticas no es que se usen demasiado, eh? Adems, los puristas de la OOP (que son personas) no admiten nada esttico, ni propiedades ni mtodos, salvo en una excepcin: las constantes.

Constantes

S! Tambin podemos definir constantes en Java. Una constante, como comprenders, no slo no puede cambiar de valor: adems, debe ser compartida por todos los objetos. Vaya una constante tan estpida aqulla que no es la misma en todos los objetos de la clase donde esa constan te se define. En Pascal, C, C+ +, BASIC, etc etc etc las constantes se definen como const (de constant). Bueno, pues en Java, como es un lenguaje tan especialito el jodo, se definen con final . Es decir, que si yo quiero definir una constante, por ejemplo, pi , hago: static final int pi = 3,1415 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2 6 4 3 3 8 3 2 7 9 5; Hala. Ahora pi es una variable compartida por todos los objetos de la clase en la cual hemos definido la propia pi , y adems no puede cambiar de valor. Hala. Antes de seguir adelante, ya sabes... VARIABLE COMPARTIDA MODIFICADOR STATIC MTODO COMPARTIDO LLAMADAS A MTODOS MEDIANTE EL NOMBRE DE LA CLASE ( Mesa.getNumMesasFabricadas() ) MODIFICADOR FINAL Para comerse el coco..... (3) La clase Math contiene mtodos que hacen clculos numricos, como coseno, seno, etc..... Si miras la definicin de estos mtodos, vers que ninguno se salva, todos son mtodos static . Por qu crees que es as? El mtodo main, arrays y a lanzar programas! Seguro que te has dado cuenta de que hemos definido mil clases, mtodos y propiedades, pero que realmente todava no hemos hecho ningn programa. Bueno. Vamos a solucionar eso. Un program a siempre tiene un punto de arranque, es decir, empieza en un momento determinado. Bueno, pues en Java, este punto de arranque se llama mtodo main . Un programa suele constar de varios archivos, uno por cada clase que definimos. Bueno, pues en una de estas clases debemos definir el mtodo main . Como comprenders, ser una buena prctica de programacin definir una clase exclusivamente para albergar el main . No es necesario, pero es muy buena prctica, es decir, que al margen de toda nuestra fabulosa coleccin de clases definimos otra ms cuyo contenido sea un slo mtodo main . Bueno, pero vamos con el propio mtodo.

El main se define siempre igual, por norma en Java. Es un mtodo: esttico: ya sabes qu es esto. pblico: si lo sabes, te felicito. Bsicamente significa que puede accederse a este mtodo desde cualquier lugar, a diferencia de otros mtodos que pueden ser privados. Bueno, ya lo veremos, vale? no devuel ve datos: se define como void se llama siempre main recibe como argumentos un array de Strings: tambin lo veremos. main queda definido entonces como: public static void main(String[] IDENT) Como comprenders, IDENT es un identificador al que puedes llamar como te d la gana. Normalmente recibe el nombre arg o args . Para qu sirve? Cuando ejecutam os un programa Java, lo que hacemos es escribir java clase y esto invoca a la JVM. Pero nosotros somos muy listos, y podemos arrancar el programa pasndole argumentos: java clase arg1 arg2 arg3 ... argn Bueno, pues la JVM coge estos argumentos los mete en una lista. A este tipo de listas se les denomina array , y funciona de la siguiente manera: Un inciso: arrays Un array es una lista ordenada de elementos. Cada elemento tiene asociado un ndice. El primer ndice es el cero, y el ltimo depende del nmero de elementos que haya guardados en el array. Un array, como una variable cualquiera, tiene un TIPO (int, float, String...) y un IDENTIFICADOR. Veamos cmo se declaran: tipo[] IDENT = new tipo[tamao]; por ejemplo, hagamos un array de Strings de 5 posiciones: String[] miArray = new String[5]; y usamos el array como si fuese una variable normal, pero teniendo en cuenta los ndices en los que guarda mos valores:

miArray[0] miArray[1] miArray[2] miArray[3] miArray[4]

= = = = =

Posicin primera...; ... segunda...; ...tercera...; ...cuarta...; y al siguiente da dej el colegio;

Para saber el nmero de posiciones de un array usamos el operador .length Fjate en el punto inicial de .length !: int tamao = miArray.length; Ahora tamao vale 5. sacab el inciso. Sigamos con el main. public static void main(String[] args) Cuando invocamos a la JVM, sta argumentos que hemos introd ucido en java clase arg1 arg2 arg3 ... y crea el array que hemos llamado args . Bueno, Podemos, por ejemplo, escribir un programa al que le pasemos como argumentos un color y la forma, y l nos cree una mesa con cuatro patas y con ese color y esa forma. Usando System.out.println podemos mostrar en pantalla las propiedades de la mesa. Meteremos MesaMain.java): el main en una nueva clase MesaMain (archivo determina el nmero de

class MesaMain{ public static void main(String[] args) { Mesa Margarita = new Mesa( args[0], 4, args[1] ); System.out.println(Hemos creado una mesa); System.out.println(con +Margarita.getNumPatas()+ patas,); System.out.println(de color +Margarita.getColor()); System.out.println(y de forma +Margarita.getForma()); } } Ahora, si compilamos Mesa y MesaMain con: javac Mesa.java javac MesaMain.java

y hacemos: java MesaMain rojo, redonda el program a nos dice: Hemos creado una mesa con 4 patas, de color rojo y de forma redonda Hala. Nuestro primer programa. Es una pena, normalmente el primer programa que se escribe es mostrar en pantalla el saludo Hola mund o!, pero alguna vez hay que saltarse las reglas, no? De todas formas eres perfectamente capaz de programar tal saludo, no? Haz una clase Saludo que contenga un main que muestre en pantalla el saludo Hola mundo!. En total, cinco lneas de cdigo. Cuidado! El programa MesaMain exige que metamos al menos dos argumentos. Si ponemos slo uno, habr un error, y si ponemos siete, los ltimos cinco se ignorarn. Programando a lo bestia. Estructuras de control. Hay una serie de estructur as que la mayora de los lenguajes de programacin poseen. Son las estructuras del control . Estas estructur as son funda ment almente las condicionales y las repetitivas . Empecemos por las primeras. Sentencias condicionales sentencia if if es la estructur a condicional por antono ma sia en todos los lenguajes. Su sintaxis es muy fcil: if (condicin) { bloque1 } else { bloque2 } Si cualquier bloque consta slo de una sentencia , entonces las llaves correspon dientes a ese bloque pueden eliminarse. Es cuestin de comodidad. Expliquemos. la condicin es una expresin lgica, es decir, booleana. Si esta expresin da como resultado TRUE, se ejecuta el

bloque1 , mientras que si la expresin es FALSE se ejecuta bloque2 . As de simple. Claro, que queda un poco al aire eso de la expresin booleana. Vemosla: Una expresin booleana es cualquier cosa que pueda dar como resultado TRUE o FALSE. Por ejemplo, la comparacin de dos variables.Este es un buen momento para ver los comparadores de magnitud : == != > < >= <= igual a diferente de mayor que menor que mayor o igual que menor o igual que

Una expresin lgica puede ser combinacin de expresiones lgicas ms pequeas combinadas con los Y, O, NO que ya conocemos, verdad? En Java se escriben as: AND && OR || NOT ! Bueno, pues ya no deben asustarte cosas como ((n1 > 5) && (n2 < 3)) || !(n3 >= n4) Otro tipo de expresin booleana puede ser un valor boolean devuelto por un mtodo. Veamos un ejemplo: Para saber si dos nmeros son iguales utilizamos el smbolo == if (num1 = = num2){ System.out.prinln(Son iguales); } else { System.out.println(Son diferentes); } Sin embargo, para saber si dos String son iguales no podem o s utilizar el simbolo de igualdad. Es una peculiaridad de Java que no viene ahora a cuento:

Aparentemente, si tenemos String string1 = Hola; String string2 = Hola; String string3 = Adis;

la expresin booleana ( string1 = = string2 ) debera ser TRUE, pero no es as. Para comparar Strings utilizamos el mtodo .equals() ste es un mtodo que funciona de la siguiente manera: partiendo de las strings anteriores, string1.equals(string2) da un resultado de TRUE, mientras que string1.equals(string3) da como resultado FALSE. En definitiva, .equals() es el mtodo que utilizamos para comparar una String con otra. Como ves, un mtodo puede devolver un valor booleano, por lo que este valor puede ser utilizado en una sentencia if : if (string1.equals( string2 )) { System.out.println(Son iguales); comparan } else { >= <= System.out.println(Son diferentes); comparan } .equals() RECUERDA: los nmeros se con == != > < pero las Strings se con

por supuesto, dentro de un bloque de un if podemos anidar ms if s: if (tal y cual) { hacemos esto if (nosequ){ pues esto otro } else { y si no, esto } } else { if (vaya rollo){ bah, yo me piro } else { paso de todo } } Una sentencia if puede definirse sin su else correspon diente:

if (string1.equals(string2)){ System.out.println(Son iguales); } . . . Pero hay que tener mucho cuidado con esto, sobre todo si anidamos if s. Supongamos que queremos comparar dos enteros n1 y n2 , y saber si son iguales o si n1 > n2 . No nos importa saber si n2 > n1 . Recuerda que cuando un bloque consta slo de una sentencia (que puede ser perfectamente una sentencia if ), las llaves pueden eliminarse. int n1 = 1; int n2 = 10; if (n1 != n2) if (n1 > n2) System.out.println(n1 > n2); / / no comprobam os si n2 > n1 else System.out.println(Son iguales); Bueno, pues este fragmento es errneo. Si n1 y n2 son iguales, el programa no avisa. De hecho, tomando los valores 1 y 10, el programa dice que son iguales. La razn es que el else aparenteme nte pertenece al primer if , pero en realidad pertenece al segundo if ! El fragmento correcto sera el siguiente: int n1 = 1; int n2 = 10; if (n1 != n2) if (n1 > n2) System.out.println(n1 > n2); else / / cualquier sentencia que no ejemplo n1 = n1; else System.out.println(Son iguales);

haga

nada, por

Bueno, hay que pasar siempre por estas cosas! Mucho cuidado cuando anides if s, pon siempre sus else s, aunque no hagan nada. Otra opcin, tal vez te guste ms, es la siguiente:

int n1 = 1; int n2 = 10; if (n1 != n2) if (n1 > n2) System.out.println(n1 > n2); else { } / / bloque de cdigo vaco else System.out.println(Son iguales);

Aqu hacemos uso de un bloque vaco , lo delimitamos con { }, y sin embargo no metemos nada entre esas llaves. Bueno, todo son opciones. Personalmente te recomiendo que cuando empieces a programar siempre escribas las llaves, aunque encierren una sola sentencia, o aunque estn vacas: int n1 = 1; int n2 = 10; if (n1 != n2) { if (n1 > n2) { System.out.println(n1 > n2); } else { } } else { System.out.println(Son iguales); } As siempre vers claramente los bloques y la dependencia de if s y else s. Como vers en las pruebas de programas , las sentencias condicionales son siempre una fuente de errores, debido, por ejemplo, a cosas como estas. Estos errores se eliminan mediante las pruebas de caja blanca , es decir, conociendo el cdigo del programa. Si tienes que probar un programa y te dan el cdigo, mira siempre la dependencia de if s y else s, vale? sentencia switch Esta sentencia es muy peculiar. Permite ejecutar determinada parte de un fragmento de cdigo en funcin de un nmero enteo. Me explico. switch (expresin) { case caso1:

bloque1 case caso2: bloque2 . . . } Bueno, pues esto es fcil. Vamos a ver. expresin es un nmero entero. Si hay algn caso que coincida con ese nmero entero, entonces se ejecutan todos los bloques que haya a partir de ese caso, no slo el bloque que correspond e a ese caso. Un poco raro, no? Bueno, veamos un ejemplo: switch (n){ case 1: System.out.println(uno); case 2: System.out.println(dos); case 3: System.out.println(tres); } Date cuenta de que no es necesario poner llaves, sean los bloques como sean, una sentencia o ms. Si n = 1 , por lo que se ejecuta el caso 1 y todos los casos posteriores , es decir, el 2 y el 3. Por eso, si n = 1 se imprimira en pantalla uno dos tres

mientras que si n = 2 se imprimira dos tres y si n = 3 , pues se mostrara tres Por la razn que hemos visto. Repito. Se ejecuta el bloque que corresponde al caso y los bloques siguientes. Por eso, si n = 1 , se ejecuta el caso 1 y los siguientes, es decir, los casos 2 y 3.

Hay alguna forma de hacer que se ejecute slo el caso que correspo n da, y que no se ejecuten los casos siguientes? Pues claro! usando break :

switch (n){ case 1: System.out.println(uno); break; case 2: System.out.println(dos); break; case 3: System.out.println(tres); break; } ahora, si n = 1 , se muestra en pantalla uno a diferencia de antes. Otra cosa sobre los switch es: existe un caso especial, el llamado default . Se ejecuta este caso si no hay otro caso que correspon da a la expresin: switch (n){ case 1: System.out.println(uno); case 2: System.out.println(dos); case 3: System.out.println(tres); case default: System.out.println(ms de tres); } Aqu, si n = 4 , se mostrara en pantalla ms de tres mientras que si n = 1 , se vera uno dos tres ms de tres

Bueno, no es tan mortal. Para comerse el coco...... (4) se te ocurre algn error en el siguiente cdigo de programa? switch (n){ case 1: System.out.println(uno); break; case 2: System.out.println(dos); break; case 3: System.out.println(tres); break; case default: System.out.println(ms de tres); } piensa, piensa............ Sentencias repetitivas (o iterativas) Adivina por qu se llaman as. Nos permiten repetir determinado fragmento de cdigo un nmero definido de veces. En realidad lo que se hace es determinar una condicin, una expresin lgica . As, mientras esta expresin sea TRUE el fragmento se repite, hasta que sea FALSE. Es decir, que no definimo s un nmero de repeticione s , sino una condicin para que se repita . Naturalmente podemos adecuar una condicin para que un fragmento se repita un nmero determinado de veces. Bueeeno, poco a poco. Vale. Ya hemos tomado contacto con las expresiones lgicas, verdad? Fantstico. Aprndetelas bien, porque las vas a usar muncho muncho muncho. while permite repetir un bloque mientras una condicin sea TRUE. Primero se comprueba la condicin, y si es TRUE entonces se ejecuta el bloque: while (condicin){ bloque } Un ejemplo: int n = 0;

System.out.println(a contar); while (n < = 1 0) { System.out.println(Voy por el +n); n = n + 1; } System.out.println(Ay!, que me canso); Bueno, pues est claro, este fragmento inicializa n a cero, y mientras n < = 10 hace lo que est entre llaves, es decir, imprimir el mensaje y aumentar n en una unidad. Es decir, cuenta de cero a diez. Por supuesto puedes meter while s, if s y todo lo que quieras dentro de un while . Esto ya lo sabrs, pero es mi obligacin avisarte: Las sentencias repetitivas son una fuente inagotable de errores. Tienes que tener mucho cuidado a la hora de usarlas, que va a ser siempre, por cierto. Por favor, ten mucho cuidado en cmo usas las cosas, cmo planteas las condiciones, el orden de las lneas dentro de un bloque.... cualquier cosa puede hacer que tu programa estalle. Qu ocurrira si invertimos el orden de las dos lneas del bloque del while anterior? y si ponemos como condicin n < 10 ? Por estas razones suele haber una regla, que no siempre se cumple, ni tienes por qu cumplirla, pero es conveniente: primero, inicializamo s las variables en el primer caso del bucle . Si quiero contar de 0 a 10 empiezo en 0. Parece obvio, pero no lo es. segundo, la condicin tiene que aceptar el primer valor . Es estpido que no pueda entrar en el bucle en el primer caso. tercero, las variables se actualizan al final del bloque . Es decir, es aconsejable que las variables cambien de valor justo en el final del bloque, no en la mitad ni al principio. Fjate, el n = n + 1 est al final. Repito que no es una regla general, que no tiene por qu ser as, pero que conviene. De hecho, seguir esta regla a veces complica la existencia una barbaridad. una variante de while: do while while , como hemos dicho, primero compr ueba la condicin y si es TRUE ejecuta el bloque. do while (o duguail para los amigos) primero ejecuta el bloque y luego compr ueba la condicin. De esta forma, while puede no ejecutar nunca un bloque, ya que primero compr ueba la

condicin, pero do while, al comprobar la condicin al final, siempre ejecuta el bloque al menos una vez . Tpica pregunta de examen. Bueno, la estructur a es semejante a la del while : do { bloque } while (condicin) Y esas reglas de antes, yo que t intentaba aplicarlas aqu tambin. for Esta es la ms complicada de todas. Se basa en lo siguiente: Fjate que while y do while tenan como tres partes: inicializacin de las variables condicin actualizacin de las variables te suena? int n = 0; / / INICIALIZACIN

System.out.println(a contar); while (n < = 1 0) { / / CONDICIN System.out.println(Voy por el +n); n = n + 1; / / ACTUALIZACIN } System.out.println(Ay!, que me canso); Bueno, pues for resume estas tres partes en una sola sentencia: for (inicializacin, condicin, actualizacin){ bloque } Por ejemplo: System.out.println(a contar); for (int n = 0; n < = 10; n = n + 1){ System.out.println(voy por el +n); } System.out.println(Ay! que me canso);

Te percatas de cmo for resume las tres partes en una sola sentencia? Bueno, Crees que hay ms sentencias repetitivas? Pues nooooop. En realidad puedes hacer una diferenciacin muy simple: for se usa cuando sabes cuntas veces se va a repetir un bucle, y while en caso contrario. Por ejemplo, si vas a recorrer un array usars un for porque sabes la longitud del array, sabes su tamao. Si buscas una letra en una cadena de caracteres usas un for porque sabes cuntos caracteres tiene esa cadena (usando el mtodo .length() de la clase String, no lo confun da s con el .length sin parntesis de un array), pero si esperas a que el usuario introdu zca una clave, por ejemplo, usars un while porque no sabes cuntas veces va a teclear una clave incorrecta. Y recuerda, do while no es ms que un caso de while . Sabes que con lo dicho hasta ahora puedes programar cualquier cosa? Bueno, pero no saltes de alegra hasta haberte convencido de que pilotas los conceptos de SENTENCIAS CONDICIONALES IF / ELSE SWITCH / CASE / CASE ELSE SENTENCIAS REPETITIVAS WHILE / DO WHILE / FOR Para comerse el coco.....(5) Ya sabes que for engloba una inicializacin, una condicin y una actualizacin. En qu momento del bucle se produce cada una de estas partes? Debo decirte que todo en programacin se aprende primero mediante teora, y luego mediante horas de prctica. Eso ya lo sabes. Pero en el uso de bucles y condicionales es especialmente necesario que practiques con ellos. Trata de hacer programas simples (que sean un un solo main ) que, por ejemplo, cuenten de un nmero a otro, que cuenten pares, impares, que calculen sumatorios, factoriales..... Se te ocurre alguna forma de calcular los 100 primeros primos? Puedes implementar la criba de Erasttenes con dos bucles for anidados y un array de enteros..... En fin, que cualquier cosa que se te ocurra, a por ella sin temor. Hazlo por m.... Cosas que nunca se deberan hacer: break y continue Existen dos sentencias, break y continue, que pueden ayudar a resolver ciertos problemas a la hora de entrar y salir de los bucles. Son realmente tiles pero, personalmente, no te recomiendo que las uses, porque pueden dar lugar a que tu cdigo sea ilegible y poco abordable. Slo es una opinin.

Break En realidad, break ya lo hemos visto con la sentencia switch. Break lo que hace es justo lo que parece: salir de un bucle: for (un bucle enorme) { if (se cumple cierta condicin) break; } En cuanto se cumple la condicin, saldremos del bucle. Tan simple como eso. Personalmente, creo que hay maneras ms elegantes de solucionar esto: for (inicio; condicin1; actualizacin) { if (condicin2) { ... } else { break; } } Este fragmento lo que hace es iterar las sentencias ... hasta que la condicin 2 deje de cumplirse. Por ello, se podra traducir por: for (inicio; condicin1 && condicin 2; actualizacin) { ... } que es bastante ms elegante, pero para gustos estn los colores, no? Continue La sentencia continue se utiliza para, dentro de un bucle, acabar la iteracin actual y comenzar la siguiente. Por ejemplo: for (inicio; condicin1; actualizacin) { if (! condicin 2) { continue; } ... } Este fragmento funciona de la siguiente forma: al iterar, si no se cumple la condicin 2, se sigue iterando, de forma que las sentencias ... se ejecutan slo si la condicin 2 se cumple. Por ejemplo, suponga mo s que tenemos una lista de nombres y queremos saber cuntos hay mayores de edad:

for (i=0; i<nu m eroPersonas; i+ +) { if (persona[i].edad < 17) continue; mayoresDeEdad + +; } Personalmente, creo que es bastante ms legible hacer for (i=0; i<nu m eroPersonas; i+ +) { if (persona[i].edad > = 17) mayoresDeEdad + +; } pero la eleccin, de nuevo, es tuya. Adicionalmente a todos estos mecanismos de control del flujo del programa, existe algo llamado etiquetas (labels). Una etiqueta sirve para dar un nombre a una sentencia, por ejemplo: etiqueta: for (inicio; condicin; actualizacin) { ... } Las etiquetas son tiles para hacer burradas como la siguiente: etiqueta: for (inicio; condicin; actualizacin) { for(inicio2; condicin 2; acualizacin 2) { if (condicin3) break etiqueta; ... } } En caso de que se cumpla la condicin 3, si hubiramos puesto break solamente, el segundo bucle se acabara, pero el primero seguira funcionando. Haciendo break etiqueta rompem os el bucle marcado por la etiqueta, es decir, nos cepillamos ambos bucles de un pluma zo. En fin, no te lo recomiendo, pero si te gusta, ya sabes :)

Existe otra forma de abordar los problemas que se resuelven mediante sentencias repetitivas. Es una visin muy diferente y que, desgraciadame n te, cuesta mucho entender. As que tratar de esforzar m e. Es el temido tema de... Recursividad Como acabo de decir, la recursividad es una forma de solucionar problemas. Siempre se dice que todo algoritmo iterativo puede traducirse a una forma recursiva, y viceversa. Bueno, pues es cierto: si tienes un algoritmo iterativo puedes cambiarlo y convertirlo en recursivo. De hecho es una pregunta muy propia de los exmenes de Laboratorio de Programacin. Bueno, vamos a ver entonces qu es esto de la recursividad. La recursividad es un concepto muy abstracto. As que atencin. Consiste en que un fragmento de cdigo se usa a s mismo . Ese es el coraz n de la definicin. Por ejemplo: hay un cuento que narra cmo un prncipe se meti en un gran barrizal, el cual le impeda caminar, ya que el lodo era demasiado denso. As que lo que hizo para salir fue tirar l mismo de sus botas hacia ariba, primero una, luego la otra, y as consegua la fuerza suficiente para avanzar por el barrizal, y logr salvarse. Bueno, es un ejemplo muy simple de cmo algo puede usarse a s mismo. Desgraciadamente abordare mo s este tema de una forma ms difcil. Hay un ejemplo tpico del uso de la recursividad. Es el clculo de factoriales. Ya sabes:
n! = n (n-1) (n-2) ... 3 2 1

pero, fjate:
n! = n (n-1) (n-2) ... 3 2 1 (n+1)! = (n+1) n (n-1) (n-2) ... 3 2 1

entonces,
(n+1)! = (n+1) n!

y, por tanto,
n! = n (n-1)!

Vale. Cursillo intensivo de Calculo I. Bueno. Observa que la definicin de factorial engloba un factorial. Por eso es recursivo. Para ver fcilmente cmo funciona la recursividad, considerar el siguiente ejemplo. A ver si te gusta. vamos a

Supn la cola de la taquilla del cine. Si, antes de entrar a ver la pelcula hay unas cuantas personas compran do la entrada. Aqu las

tenemos: En un momento dado, el ltimo de ellos, el de la camiseta amarilla, desea saber a qu hora es la siguiente sesin. As que lo que hace es preguntr selo al de la camiseta roja:

Pero, claro, resulta que el de la camiseta roja tampoco lo sabe. Un fastidio. As que lo que hace es preguntrselo al de las rastas, mientras mantiene al de la camiseta amarilla a la espera.

Pero el de las rastas tampoco lo sabe. As que hace la misma pregunta al de los zapatos amarillos, mientras mantiene al de la camiseta roja a la espera. Por supuesto, el de la camiseta amarilla sigue a la espera

de que le responda el de rojo.

En fin, puedes adivinar que el de los zapatos amarillos no tiene ni idea, as que lo que hace es preguntrselo a la taquillera de los pelos rojos. El de las rastas se queda esperando a que el de los zapatos amarillos le responda. A todo esto, el de rojo est esperando al de las rastas, y el de la camiseta amrilla est hartndose de esperar.

Pero vaya! resulta que la taquillera de los pelos rojos, a pesar de ser su primer da de trabajo, est muy puesta en el tema y sabe la respuesta. Claro, que ella responde a quien le ha pregunta do, al de los zapatos amarillos:

Ahora que el de los zapatos amarillos sabe la respuesta, se la dice al de las rastas, que le estaba esperando. El de rojo sigue esperando, claro, y el de la camiseta amarilla, ni te cuento. Ahora el de las rastas ya sabe la respuesta. Pues va y contesta a quien le ha pregunta do. El de la camiseta amarilla, todava sigue esperan do.

Una vez que el de rojo sabe la respuesta, por fin, se la dice al de la camiseta amarilla, que es el primero que pregunt, justito antes de que le diera un ataque de histeria.

En fin, acabas de ver intuitivamente (espero) cmo funciona un algoritmo recursivo. El primero llama al segundo y espera a que le respon d a. El segundo llama al tercero y espera a que le responda, mientras el primero sigue esperando. Y as sucesivamente... y as recursivamente.... Todo mtodo recursivo tiene parmetr os y valor de retorno. Es parte del juego. Por qu? Bueno, vayamos poco a poco. Un algoritmo recursivo trata de resolver un problema, por ejemplo, el mtodo factorial() halla un factorial., por ejemplo, 5!. Si queremos calcular 5! debemos pasar ese 5 al mtodo: float resultado = factorial(5); Lo cual ya es una buena razn para pensar que el mtodo necesita parmetros. Pero, lo mejor de todo, y lo ms importante es que el propio mtodo factorial() llamar a factorial() pero con otro parmetro . factorial(5) llama a factorial(4) , y ste a factorial(3) , y as sucesivamente. Por tanto, es ms que obvio que un mtodo recursivo necesita parmetros. Ufff... Pensar que un mtodo recursivo no ha de tener parmetros es como pensar que en la cola del cine el de la camiseta amarilla pregunta al de rojo disculpe, podra decirme?

Decamos que un mtodo recursivo siempre devolver un valor. Claro, Por qu? Pues muy sencillo: cuando factorial(5) llama a factorial(4) lo hace para averiguar el factorial de cuatro. As que factorial(4) debe devolver un valor, exactamente 24. Pensar que un mtodo recursivo no devuelve ningn valor es como pensar que en la cola del cine el de rojo responde al de amarillo claro! la pelcula empieza a las. Joer, imagina la conversacin. En definitiva, esto es una especie de demostracin intuitiva para que te percates de que un mtodo recursivo necesita, exige, precisa y requiere parmetros, y siempre devuelv e algn valor. Si algn mtodo recursivo no tiene parmetro s y/o no devuelve algn valor, es porque tiene un diseo extrao, poco comn. Mi compaero de la prctica de Programacin, primer cuatrimestre, resolvi varios problemas de la prctica mediante un mtodo recursivo que ni tena parmetr os, ni devolva valores. Y funcionaba a las mil maravillas. Pero, repito, es un caso muy raro. Yo jams habra hecho tal mtodo recursivo, sino iterativo. O sea, que la mxima de antes no es tal mxima, pero yo te aconsejo que la sigas siempre que puedas. Todo mtodo recursivo consta de tres partes. Primero veamos esas partes y luego te pondr un ejemplo, vale? a) caso base : el caso en el que no se necesita una llamada recursiva. Por ejemplo, factorial de 1. b) caso no base : el caso en el que se hace la llamada recursiva. Por ejemplo, el factorial de 36. c) conquista : consiste en, despus de hacer la llamada recursiva , obtener el resultado que piden al mtodo. El caso base podramos relacionarlo con la taquillera de los pelos rojos. Ella puede contestar a la pregunta sin necesidad de preguntar a nadie ms, es decir, sin hacer ninguna llamada recursiva. El caso no base es cualquiera de las personas de la cola: para resolver la duda han de plantersela a otra persona, no pueden resolverla por s mismos. La conquista sera un poco ms rara: el paso de la respuesta que a uno le ha llegado hacia la persona que le ha preguntado. Es decir, el de rojo lleva a cabo la conquista cuando el de las rastas le responde, y el de rojo toma esa respuesta y se la da al de amarillo. No confunda s caso no base y conquista: el caso no base es la condicin, y la conquista es la accin. Huy, qu bonito. Bueno, lo prometido es deuda. Vamos a implementar el mtodo factorial . Lo implementare m o s poco a poco, as que no te hagas un lo con las llaves, vale?

Bueno: primero necesitamos devolveremos un entero largo: long factorial( int numero ) {

parmetr os,

un

entero,

Vamos a definir un entero largo, que ser la respuesta que el mtodo devolver: long respuesta = 0; Ahora debemos diferenciar entre caso base y caso no base. El caso base ser el factorial de 1, y el caso no base, cualquier otro. if ( numero = = 1 ) { respuesta = 1; } else { / / caso base

Ahora viene el caso no base. La respuesta se hallar mediante la llamada recursiva. Ya que n! = n * (n- 1)!, haremos: respuesta = numero * factorial(numero 1); } Y por ltimo, la conquista. Debemos devolver la respuesta que hemos hallado a quien nos lo pregunta: return respuesta; } Aqu est el mtodo al completo:

long factorial( int numero ) { long respuesta = 0; // lo que devolveremos

if ( numero == 1 ) { // caso base respuesta = 1; // devolveremos 1 } else { // caso no base: llamada recursiva respuesta = numero * factorial(numero 1); } return respuesta; } // conquista!

Pues nada, esto compila perfectamente, y funciona. Por cierto, este cdigo no tiene tratamiento de errores, as que no le hagas perreras, tipo factorial(- 3), porque se te va a quedar ms colgao que el telefrico. Claro, que... Por qu no le haces t las medidas de seguridad? No es difcil... nimo! Bueno, ahora voy a contarte un pequeo truco que nadie cuenta para entender bien el funcionamiento de un mtodo recursivo. Vers, cuando un mtodo se llama a s mismo, imagina que lo que ocurre es que en la memoria del ordenador se hace una copia del mtodo. As que lo que t deberas hacer para entender un mtodo recursivo es pensar que existen varias copias del mtodo en memoria. Si tienes este cdigo:

long factorial( int numero ) { long respuesta = 0; if ( numero == 1 ) { respuesta = 1; } else { respuesta = numero * factorial(numero 1); } return respuesta; }

Trata de pensar que, cuando el programa arranque, por ejemplo, al calcular el factorial de 3, lo que tendrs es esto:

Uff... no se ve muy bien... he tenido que reducir mucho la letra para que entren las tres copias. Sorry. Bueno, pues con esta imagen t puedes imaginar el proceso que se lleva a cabo al calcular factorial(3) . El trascurso del programa est marcado con la lnea roja. El dibujo est en la pgina siguiente, porque es un poco grande. En l puedes ver cmo la primera llamada viene desde las alturas, en la parte de arriba a la izquierda. Esa llamada mete el 3 como parmetr o en la primera copia de factorial . ste, al ver que no es un caso bsico, hace la segund a llamada pasando como parmetro 2 a la segunda copia del mtodo. La segunda copia acta de forma semejante, pasando 1 a la tercera copia. sta identifica que es el caso bsico y conquista la respuesta, en este caso 1. La respuesta vuelve a la segunda copia, quien lleva a cabo la segunda conquista, devolviendo a la primera copia 2. La primera copia, a su vez, lleva a cabo su conquista devolviendo al ente en las alturas 6.

Espero que haya sido una explicacin muy grfica. Creo que no soy capaz de explicarlo de otra manera mejor, as que, si no lo has pillado bien, releelo todo despacito. Trata de ir muy lentamente, viendo cmo se comporta cada copia de factorial , identificando cada paso con la situacin de la cola del cine, vale? Espero que hayas perdido el miedo a la recursividad, y estoy convencido de que cada vez que preguntes algo a alguien, y este alguien se lo pregunte a otro te acordars de todo esto. Hala. Se acab. Crees que te voy a dejar sin la lista de conceptos? Pues noooooo... MTODO ITERATIVO / RECURSIVO METODOLOGA DE LA RECURSIN: la cola del cine MTODO RECURSIVO PARTES DE UN MTODO RECURSIVO caso base, caso no base, conquista

Como curiosidad.... Sabes por qu se le llama conquista? Pues es muy sencillo. Los mtodos recursivos se suelen usar para resolver problemas partindolos en cachitos ms pequeos. Por ejemplo, buscar a una persona en una cola de gente: primero buscas en la mitad izquierda, y luego en la derecha. Esto lo vers muy profunda m e n te en Laboratorio de Programacin. Bueno, pues como ya sabrs, hay un refrn rabe que dice: divide y vencers . En ingls, divide and conquer. De ah lo de conquista.

Bueno, vamos a abordar una de las partes ms bonitas de la OOP, aunque trae sus dolores de cabeza, no te creas. Algunos lenguajes, como C++ basan gran parte de su ingente potencial en esto que llamamos... Herencia Bueno, est claro qu es la herencia. Es lo que unos padres dejan a sus hijos. O mejor dicho, lo que unos padres transmiten a sus hijos por va gentica. Las personas somos creadas mediante herencia de genes, a pachas entre papi y mami. En definitiva, que pap y mam no nos definen desde el principio, sino que toman sus propios genes para crearnos a nosotros. Bueno, afortuna da m e n t e esto no es tan fcil en gentica como en programacin. Pero el concepto que te tiene que quedar muy claro es que la herencia es un mecanis m o de definicin, no un mtodo para suspender a los de primero de Teleco, ni un galimatas conceptual, sino que es una forma de definir nuevos objetos a partir de los existentes. La herencia sirve para definir. En Java una clase slo puede heredar de otra clase . No se admite que una clase herede de varias clases, como s se puede hacer, por ejemplo, en C++. En Java, por tanto, no hablamos nunca de herencia mltiple . Adems, la herencia en Java se denomina extensin : decimos que una clase extiende a otra. Por tanto tenemos que tener en cuenta que, en Java, los objetos slo tienen un padre, y adems, heredan de l el 100%, no como en las personas que heredan el 50% Bueno, pues sin ms prembulos nos podemos plantear alguna estructura jerrquica , es decir, algn diagrama de clases en el que dichas clases se relacionen mediante mecanismos de herencia. Por ejemplo, se me ocurre pensar que una moto es como una bicicleta con motor. De ah lo de motocicleta. Bieeeeen

Bueno, pues pasemos a escribir. Por cierto, muchas el fin de este cdigo que ahora vamos a escribir es definidas de forma puramente didctico, no funcional. veces incluso es porque Es decir, que vamos a definir una contenido bicicleta y una moto, pero de una nada. forma muy estpida. Vers: vamos a definir las clases Rueda y Motor de una forma un tanto peculiar, aunque simptica donde quepa:

veremos clases muy tonta. A sin definir. Eso realmente su no importa

class Rueda { void saludar() { System.out.println(Soy una rueda); } } class Motor { void saludar() { System.out.println(Soy un motor); } } Ahora hacemos que una bicicleta sea, simplemente, dos ruedas: class Bicicleta { Rueda delantera; Rueda trasera; Bicicleta(){ / / el constructor delantera = new Rueda(); trasera = new Rueda(); } void saludar() { System.out.println(Soy una bicicleta); } }

Bueno, pues vamos a definir la moto. Para hacer que una clase hijo extienda a otra padre , la primera clase se define as: class hijo extends padre Bueno, pues a ello. class Moto extend s Bicicleta { Motor motor; Moto() { / / el constructor motor = new Motor(); } void saludar(){ System.out.println(Soy una amoto); } } Estas cuatro clases son lo ms fcil del mundo. Si no las entiendes, para y vuelve atrs, porque son de lo ms bsico. Pero seguro que las entiendes sin problemas, verdad? Fjate en el uso de la herencia: la clase Moto slo define un mtodo saludar y una propieda d Motor , pero hereda de la clase Bicicleta , por lo que tambin posee todos los contenidos de Bicicleta . Por tanto, Moto hereda de la clase Bicicleta las dos ruedas. Te percatas de cmo se usa la herencia para definir clases? Definimos el contenido de Moto a partir del contenido de Bicicleta . Respecto al mtodo saludar , fjate que Motor redefine el mtodo saludar que hereda de Bicicleta . La clase padre tena un mtodo saludar , pero la clase hija tambin lo tiene. Se dice que lo redefine (overrides) . Sin embargo, debe quedar muy claro que redefinir un mtodo no implica que el mtodo anterior deje de existir , es decir, que el mtodo saludar de Bicicleta sigue existiendo a pesar de haberlo redefinido en la clase moto . No tendra sentido que una moto saludase como una bicicleta, no? Aunque no te creas, que gracias al casting , que en breve veremos, podemos hacer que una moto pueda saludar como moto y como bicicleta. Bueno, pues eso es todo sobre cmo se usa la herencia. Vemos cmo hemos definido una moto a partir de la definicin de una bicicleta, verdad?. Ahora, en cualquier parte del cdigo, por ejemplo, en un main podemos hacer sin problemas: Bicicleta Antonieta = new Bicicleta(); Moto Anacleta = new Moto();

Bueno, pues al crear a Antonieta se crearn las ruedas, y al crear a Anacleta se crear el motor. Podemos hacer sin problemas: Antonieta.saludar(); Anacleta.saludar(); y cada una nos saludara diciendo lo que son. Hala. Voy a compilar este cdigo a ver si da problemas...... no, parece que no los da. Vamos a plantear una cuestin: una Bici, al crearse, crea las dos ruedas. Una moto, al crearse, crea un motor. Pero, Se crean las ruedas al crearse la moto? Fjate en el constructor de la clase Moto: Moto() { / / el constructor motor = new Motor(); } Pregunta: Crees que al invocar al constructor de Moto se invoca automticame nte el constructor de su superclase Bicicleta? Desgraciada mente no. Tal y como estamos, al crear una moto se crea su motor, pero no sus ruedas. Ayayayayyyyyy.... cmo arreglamos esto?

Opcin primera : constructor de la moto:

crear

especficamente

las

ruedas

en

el

Moto() { / / el constructor delantera = new Rueda(); trasera = new Rueda(); motor = new Motor(); } Esto es perfectamente vlido. Pero hay otra solucin ms mejor: Opcin guai: Hacer uso de la palabra super() . Esta palabreja se utiliza en el constructor de una clase para llamar al constructor de su superclase. Es decir, que si hacemos: Moto() { / / el constructor super(); motor = new Motor(); }

entonces, cada vez que creemos una moto se crear la bicicleta que reside en su interior (oh! una lgrima resbala por mi mejilla....) y

luego el motor. Es como si al crear a una persona primero En definitiva, creas lo que tiene de su cuando una clase extiende padre y luego creas el a otra, el constructor de la resto de cosas. clase hija debe llamar al Una visin muy peculiar, constructor de la clase madre, no crees? y esto se hace mediante Por cierto, conviene super() . que super() sea lo primero que aparezca en el constructor, antes de cualquier otra sentencia. Te has preguntado por qu super() tiene parntesis? Deberas adivinarlo, pero por si acaso, te lo digo. super() es el constructor de la superclase, y recuerda que el constructor no es ms que un mtodo un tanto especialito, pero mtodo al fin y al cabo. Y si no recuerdas mal, los mtodos llevan parntesis siempre....

nota

Cuando una clase hereda de otra no es necesario que llame al constructor de su superclase, pero siempre que crees una clase hija, lo ms normal es que s lo haga. Plantate la lgica de este hecho: supn un mecnico que sabe que una moto es una bicicleta con motor. Si le piden fabricar una moto, entonces primero crear una bicicleta y luego le pondr un motor. Es decir, primero crea la clase padre y luego la hija. Supn ahora que defines una motopija , que es una moto con aire acondicionado . Pues al crearla, primero crears una moto y luego le pondrs el aire. Esto implica crear primero una bicicleta, luego ponerle motor para hacer la moto, y luego ponerle el aire para hacer la motopija. Vaya, dos super() ....

Weno, pues, como siempre, antes de seguir asegrate de pilotar: HERENCIA CLASE PADRE / CLASE HIJO USO DE extends REDEFINICIN (OVERRIDING) DE MTODOS (que a continuacin veremos con ms detalle) USO DE super() CONCEPTO DE MOTO CON AIRE ACONDICIONADO Animo! ya queda poco de OOP! Preludio al Casting: las referencias

Bueno, no tiene nada que ver con actores. Qu pena, verdad? Casting significa algo as como convertir. El objetivo del casting es hacer que un objeto que se ha definido mediante herencia se comporte como un objeto de una de sus superclases. Es decir, que una moto salude como una bicicleta, o que una moto deje de tener motor, o cosas por el estilo. En realidad el casting es algo un poco ms profundo, pero empezare m os por lo fcil. No te creas, acabaremos con lo difcil.... Bueno, pues recordemos las definiciones de Moto y de Bicicleta: class Bicicleta { Rueda delantera; Rueda trasera; Bicicleta(){ / / el constructor delantera = new Rueda(); trasera = new Rueda(); } void saludar() { System.out.println(Soy una bicicleta); } } class Moto extend s Bicicleta { Motor motor; Moto() { / / el constructor super(); / / llamamos al constructor de Bicicleta motor = new Motor(); } void saludar(){ System.out.println(Soy una amoto); } } Vamos a crear dos objetos: Bicicleta Antonieta = new Bicicleta(); Moto Anacleta = new Moto(); Si hacemos: Anacleta.saludar(); veremos en pantalla :

Soy una amoto Como sabemos, una moto es una bicicleta con motor. Eso significa que una moto tiene una bicicleta dentro de s. o lo que es lo mismo, que una moto puede comportarse como una bicicleta. Cmo? Ahora lo veremos. Para qu sirve? Eso lo veremos luego. Supn que tenis una vecina que conoce muy bien a tu madre, mucho mejor que a ti. Un buen da te ve y te saluda, y te dice Vaya, tienes los ojos de tu madre. Por qu te dice esto? Aparte de porque realmente puede que tengas los ojos de tu madre, la vecina te lo dice porque conoce a tu madre . Si no la conociese no podra decirlo, no? Es decir, que la vecina puede decir lo que has sacado de tu madre si conoce a tu madre. Bueno, pues una referencia , que se supone que ya sabes a la perfeccin qu es, es como la vecina. Es capaz de ver en los objetos los rasgos que conoce. Si una referencia es del tipo bicicleta , entonces ver los contenidos propios de la bicicleta en el objeto al que apunte. Por ejemplo: Bicicleta refABicicleta = new Bicicleta(); Estamos cerando una referencia llamada refABicicleta (referencia a bicicleta) que es del tipo Bicicleta y que apunta a una nueva Bicicleta ( new Bicicleta() ). Esto es claramente legal, es como si la vecina ve a tu madre, no hay nada que no conozca de ella. Pero si hacemos un truco... Bicicleta refAOtraBicicleta = new Moto(); Hacemos que la referencia refAOtraBicicleta apunte a una nueva moto. Cmo es esto posible? Pues es como la vecina que se encuentra un da contigo. La vecina ve en ti lo que has heredado de tu madre, porque conoce a tu madre . La referencia refAOtraBicicleta ve en la nueva moto lo que ha heredado de bicicleta porque conoce las bicicletas (es del tipo bicicleta) . Entonces, usando la referencia refAOtraBicicleta podemos hacer que una moto salude como una bicicleta, porque refAOtraBicicleta conoce el mtodo saludar de la bicicleta : Si hacemos refAOtraBicicleta.saludar(); veremos Soy una bicicleta aunque refAOtraBicicleta apunta a una moto!. Por qu? Pues por lo dicho, porque refAOtraBicicleta no conoce el mtodo que saluda como una moto, slo conoce el mtodo que saluda como una

bicicleta . Pretender que refAOtraBicicleta haga saludar a la moto como si fuese una moto sera como pretender que la vecina te diga que tienes las manos de tu abuelo, al que nunca conoci. Aqu tienes un pequeo grfico que tal vez te ayude: Vamos a olvidar por ahora los constructores, vale? Bueno, pues te presento a la seora referencia de tipo Bicicleta!: TACHAAAAAAN!!!

no esperars que tres flechas piensen como lo hacen el pez y los otros, no? Vaya unas ideas que tienes...... :)

Bueno, pues Por qu la referencia de tipo Bicicleta tiene esa forma? Pues fjate en cmo funciona esta referencia con un objeto de tipo Bicicleta :

Te percatas de cmo de ajusta la referencia al contenido del objeto? Una referencia del tipo Bicicleta ver todo el contenido de una bicicleta, as como tu vecina conoce a tu madre por completo. Ahora fjate en esto:

Un objeto de la clase Moto es igual que una bicicleta con dos cosas aadidas: un motor y un mtodo que saluda de forma diferente. Estos dos miembros de la clase estn arriba marcados en rojo. Fjate cmo una referencia de tipo Bicicleta puede adaptarse a un objeto de tipo Moto, pero no ve ms que el contenido de la bicicleta. En otras palabras, que la referencia no ve ningn miembro pintado en rojo. Por cierto, perdn por el desenfoque. Por supuesto, huelga decir que una referencia de tipo Bicicleta no puede apuntar a objetos que ni sean bicicletas ni hereden de bicicletas. Es decir, que una referencia de tipo bicicleta no puede apuntar a la mesa Margarita. Lstima. Espero que ahora haya quedado bien explicado, o mejor dicho, bien mostrado: 1- Que una referencia de bicicleta se acopla a un objeto moto. Una referencia de un tipo puede acoplarse a un objeto de otro tipo 2- Que una referencia de bicicleta al acolparse a una moto no ve ni motor ni el segundo mtodo saludar . Una referencia de un tipo acoplada a un objeto de otro tipo slo ve parte del contenido objeto Bueno, acabas de ver cmo funciona una referencia. Como resu men, una referencia es un conjunto de flechitas que apuntan hacia determinados contenidos de un objeto. Los contenidos a los que apuntan vienen determinados por el tipo de la referencia. Comparacin de referencias Para comprobar si pilotas el sentido de la palabra referencia, hazte la siguiente pregunta:

Tenemos dos objetos diferentes, con referencias diferentes, pero cuyas propiedades coinciden. Por ejemplo, dos mesas cuadradas azules de tres patas: Mesa Margarita = new Mesa(Azul, 3, cuadrada); Mesa Catalina = new Mesa(Azul, 3, cuadrada); La pregunta es la siguiente: Qu valor lgico (TRUE FALSE) dar la siguiente expresin? Margarita = = Catalina Pues veamos: estamos comproban do si son iguales dos referencias. Cada una de ellas apunta a una mesa cuadrada, azul y de tres patas. As que, como son iguales, esto debera dar TRUE. Pues no. Fjate: las dos mesas son azules, de tres patas y cuadradas. PERO SON DOS MESAS DIFERENTES, no son la misma mesa. Es como decir que dos gemelos, por ser idnticos, son la misma persona. Bueno, ten esto muy presente siempre, vale? Puedes comparar dos nmeos con = =, pero no dos objetos. Antes de seguir asegrate que has alcanzado la Idea platnica de los dos puntos anteriores. Si no es as, en realidad lo nico que tienes que hacer es pensar muy profunda m e n te en ello, vuelve a escribir las clases, prueba a hacer pequeos programas... recuerda lo dicho en el prefacio. Y, por supuesto, si tienes ms probelmas, aqu estoy. Arreglando bicicletas: parmetros que son referencias Supn ahora que se nos pincha una rueda de la bicicleta. Pues la llevaremos a un taller: class Taller { void arreglar(Bicicleta bici){ System.out.println(A arreglar!); } } Bueno, fjate: definimos un taller con un mtodo arreglar al que le vamos a pasar como parmetr o una bicicleta. Realmente este mtodo no hace absolutamente nada con la bicicleta que le damos a arreglar, pero repito que el objetivo de este rollo es purame nte didctico. Pues eso, que ahora podemos hacer sin problemas: Bicicleta Antonieta = new Bicicleta(); Taller elTaller = new Taller();

/ / despus de largas horas de uso... elTaller.arreglar(Antonieta); es decir, creamos una bici, un taller, y hacemos que el taller arregle la bici despus de mucho montar. Bueno, pues esto no parece complicado, verdad? Bueno, plantate lo siguiente: Si en el taller arrerglan ruedas de bicicleta, y una moto es una bicicleta con motor, va a poder el taller arreglar las ruedas de una moto? Pues claro que s! Pero no podemos hacerlo tan a la ligera. Veamos por qu. El mtodo arreglar requiere como parmetr o una Bicicleta . Sin embargo, queremos areglar una moto. Bueno, pues es aqu donde haremos el uso de referencias de antes: Crearemos primero una moto, pero tendr una referencia de tipo bicicleta: Bicicleta laMotoRompida = new Moto(); Bicicleta Y..... Si! ya podemos arreglar la moto: Taller elTaller = new Taller(); elTaller.arreglar(laMotoRompida); realidad // moto con ref.

/ / arreglamos una moto en

Te da cuen? Si arreglar necesita una bicicleta y queremos arreglar una moto, hacemos que una referencia de tipo bicicleta apunte a una moto. Bueno, pues fjate para qu sirve esto de las referencias. Te gusta? Pues vers ahora. Un taller que se precie no slo debe ser capaz de arreglar pinchazos. Tambin debera poder cambiar el aceite a los motores, no? Bueno, pues vamos a definir otro mtodo de la clase Taller. class Taller { void arreglar(Bicicleta bici){ System.out.println(A arreglar!); } void cambiarAceite(Moto laMoto){ System.out.println(El aceite miiiiierda);

estaba

echo

una

} } Bueno, pues ahora tenemos un peazo taller de la leche. Si tenemos una moto cualquiera podemos arreglarle los pinchazos y cambiarle el aceite. Pero fjate, el mtodo cambiarAceite requiere que le pasemos una moto (porque cambiar el aceite a una bici se las traera, no?), pero arreglar requiere una bicicleta. Madre ma. Necesitamos una referencia de tipo Bicicleta para arreglar la moto y otra de tipo Moto para cambiarle el aceite! Taller elTaller = new Taller(); Bicicleta refMoto = new Moto();

Si queremos cambiar el aceite a la moto, es fcil: elTaller.cambiarAceite(refMoto); Pero, para arreglar las ruedas necesitbamos una referencia de tipo bicicleta , y la referencia que tenemos es de tipo Moto . Tendremos que crear una nueva referencia: Bicicleta refBicicleta = refMoto; Esta referencia nueva apunta al mismo objeto al que apuntaba refMoto . Ahora s es lcito hacer elTaller.arreglar(refBicicleta); Bueno, pues esto es perfectamente legal, funciona. Pero coincidirs conmigo que es un engorro. Tener dos referencias de tipo distinto para un mismo objeto no es ser muy ahorrativo. Ni muy prctico, todo sea dicho. Casting Como dijimos hace una eternidad, casting es algo as como convertir. El objetivo es el siguiente: Hemos visto casos en los que un objeto necesita varias referencias de distinto tipo, como con el taller: arreglar las ruedas necesita una bicicleta, pero cambiar el aceite necesita una moto. Para cambiar el aceite a una moto no hay mucho problema, pero para arreglarle las ruedas haba que hacer una nueva referencia de un tipo diferente. Bueno, pues existe una manera de hacer esto mismo con una sola referencia . Cmo? Pues muy fcil: convirtindola .

Convertir una referencia de un tipo inicial a un tipo final se hace as: (tipo final)referencia Por ejemplo, si quiero convertir un nmero entero en uno de coma flotante (CUIDADO! no te creas que en este caso hay herencia de algn tipo, eh?) (float)miEntero O si quiero convertir una moto en bicicleta... (Bicicleta)refMoto Es decir, que usando esta conversin, puedo hacer sin problemas: Taller elTaller = new Taller(); Moto Maroto = new Moto();

y, por fin.... elTaller.cambiarAceite(Maroto); elTaller.arreglar( (Bicicleta)Maroto

);

/ / esto es casting!!!!!!!!!

Tenemos una sola referencia, llamada Maroto que es de tipo Moto , pero podemos usar esta referencia de tipo Moto en mtodos que requieran una referencia de tipo Bicicleta (como el mtodo arreglar ) porque podemos convertirla . BIEN! Relee el prrafo anterior. Vuelve a leerlo. Est claro? Seguro? Fabuloso. Realmente te parece el casting lo que te pareca antes? Hala. A modo de resumen: 1. Una moto puede saludar como una bici. Podemos hacer que un objeto de un tipo se comporte como un objeto de otro tipo. 2. El mtodo arreglar ve a una moto como si fuese una bici, mientras que cambiarAceite ve la misma moto como lo que realmente es, una moto. Podemos hacer que un mtodo vea a un objeto como si fuese de una clase y que otro mtodo vea el mismo objeto como si fuese de otra clase.

3. Esto lo podemos hacer mediante varias referencias de diferentes tipos que apunten al mismo objeto.... 4. O mediante una sola referencia y el truco del casting El Casting se acaba aqu. Con estos conocimientos puedes enfrentarte a un fragmento de cdigo que contenga conversiones de referencias, es decir, casting. Pensado puedes saber qu sentencias sern correctas y cuales no lo sern. Slo tienes que pensar qu contenidos del objeto es capaz de ver una referencia. Antes de seguir (y por supuesto despus de realizar tus ejercicios espirituales) plantate los conceptos de: REFERENCIA TIPO DE UNA REFERENCIA CMO las referencias apuntan a un objeto CMO dos referencias de diferentes tipos ven contenidos diferentes de un mismo objeto COMPARACIN DE REFERENCIAS: = = no funciona como quisiramos.... CMO un mtodo requiere referencias de determinado tipo (como parmetros) SENTIDO DE usar distintas referencias para un objeto FINALIDAD DEL CASTING SINTAXIS DEL CASTING Recuerda! Vimos cmo se usaba el casting para convertir enteros a coma flotante. A esto se le llama tambin CASTING, pero no tiene nada que ver con herencia. El Casting se usa para convertir a) tipos bsicos (de int a float, por ejemplo) b) referencias de objetos (llevamos tol rato hacindolo) Para comerte el coco.... (6) Dadas las siguientes definiciones: class A { int getn() { return 1; } } class B extends A { int getn() { return 2;

} } class ABMain { public static void main(String[] args){ A a = new A(); B b = new A(); System.out.println(numero:+a.getn()); System.out.println(numero:+b.getn()); } } Si lanzamos el programa, Qu vemos en pantalla? Madre ma, tpica cuestin de examen. Bueno, un puntito para ti. Upcasting y downcasting. Y siguiendo con el ingls, explicit and implicit casting. Este apartado es muy corto y slo sirve para que aprenda m os un par de trminos. Slo hay un pequeo problema: es un peln enrevesado. Tratar de explicarlo fcilmente, pero eso no va a ser suficiente. As que abre bien los ojos y lee cada prrafo siete veces. Para hacerlo ms corto an, vamos a seguir con la bicicleta y la moto como ejemplos, vale? Bicicleta Anacleta = new Bicicleta(); Moto Maroto = new Moto();

Upcasting: convertir una moto en una bicicleta. Es decir, convertir una referencia de un tipo hijo a un tipo padre: (Bicicleta)Maroto Downcasting: lo contrario: (Moto)Anacleta Lo recordars fcilmente si te imaginas la clase padre encima de la clase hijo. UPcasting es ir hacia arriba y DOWNcasting sera ir hacia abajo. Voy a adjuntar te este pequeo fragmento de cdigo para entender genial los dos siguientes conceptos, casting implcito y explcito: class A { int getn() { return 10; } } class B extend s A {

int getm() { return 20; } } class C { void pillaUnA ( A j ){ System.out.println("n = "+j.getn()); } void pillaUnB ( B j ) { System.out.println("m = "+j.getm()); } } Ahora supongam os declaraciones: un main cualquiera con las siguientes

public static void main(String[] args) { A a = new A(); B b = new B(); C c = new C(); . . . Weno. Es perfectamente lcito hacer: c.pillaUnA(a); c.pillaUnA(b); En el primer caso, a es una referencia de tipo A y por eso puede pasarse al mtodo pillaUnA como parmetro. En el segundo caso, AL LORO, b es una referencia de tipo B. Si queremos pasarla al mtodo pillaUnA deberamos hacer: c.pillaUnA( (A)b );

es decir, hacer UPCASTING. Sin embargo, este casting no es necesario hacerlo, porque el compilador lo hace directamente. A esto se le llama casting implcito . Hagamos ahora: c.pillaUnB(b); c.pillaUnB(a); En el primer caso, no hay ningn problema. En el segundo caso, estamos pasando una referencia de tipo A a un mtodo que requiere una referencia de tipo B. Es decir, al contrario de antes. Bueno, pues como

pillaUnB() necesita un parmetr o de tipo B, la referencia a tendremos que convertirla a una referencia de tipo B. Es decir, hay que hacer DOWNCASTING. Bueno, pues este casting no es implcito, no lo hace el compilador solito, como antes, sino que necesita que nosotros lo hagamos. A este casting se le denomina casting explcito . Por regla general, el upcasting es implcito y el downcasting es explcito . AVISO: dado el cdigo: A a = new A(); C c = new C(); podemos hacer downcasting as: c.pillaUnB( (B)a );

per fjate: la referencia a apunta a un objeto de tipo A que no tiene el mtodo getM(). Es decir, que sintcticamente el casting es lcito, pero pillaUnB() jams podr acceder al mtodo getM() del parmetro , sencillamente porque en este caso no el parmetr o no tiene dicho mtodo. Es un poco engorroso, pero bsicamente lo que te planteo es que este downcasting puede hacerse, puede compilar, pero jams va a poder ejecutarse. Ya hemos acabado! plantate de nuevo: UPCASTING DOWNCASTING CASTING IMPLCITO CASTING EXPLCITO Ejercicio: Dado el siguiente main, Qu sentencias son lcitas? cules compilan y cules no? cules tienen upcasting y downcasting? Cules tienen casting implcito y cules explcito? public static void main(String args[]){ A a = new A(); B b = new B(); C c = new C(); c.pillaUnA(a); c.pillaUnA(b); c.pillaUnA ( (A)b );

c.pillaUnA ( (B)a ); c.pillaUnB (a); c.pillaUnB (b); c.pillaUnB ( (A)b ); c.pillaUnB ( (B)a ); } Solucin: Es normal fallar en algunas, as que no te desesperes si no aciertas, eh? Por cierto, estoy seguro de que esta solucin es wena al 99%, pero no al 100%. As que si no concuerda con lo que t dices, y ests seguro de que no te has equivocado, tal vez lo haya hecho yo... De todas formas, he compilado el cdigo y parece que se cie a estos resultados. Por supuesto, lo mejor cuando tengas dudas es encender el ordenador y probar..... c.pillaUnA(a); / / normal c.pillaUnA(b); / / upcasting implcito c.pillaUnA ( (A)b ); / / upcasting explcito c.pillaUnA ( (B)a ); / / compila pero no ejecuta c.pillaUnB (a); / / requiere downcasting explcito c.pillaUnB (b); / / normal c.pillaUnB ( (A)b ); / / requiere downcasting explcito c.pillaUnB ( (B)a ); / / compila pero no ejecuta Bueno, visto esto, vamos a por la maravillosa...

La Clase Object La Clase Object es una clase que Java tiene definida en s mismo con su propio mecanismo. Es decir, que no vas a tener que definirla, as que tranki. La clase Object se define como superclase de toda clase Java. Es decir, que si defines una clase cualquiera, ser una clase que herede de la clase Object , aunque no lo definas como tal. La clase Mesa o Bicicleta son, en realidad, extensiones de Object . Fjate qu cosas. Bien. Qu contenidos tiene la clase Object ? Pues esta clase tiene unos mtodos muy extraos:

clone() , que sirve para hacer clonar objetos, equals() , para comparar objetos, getClass() , para obtener la clase de un objeto, y algunos ms. En definitiva, que la clase Object tiene un contenido bastante rarito. Cul es el sentido de este contenido? Pues muy fcil: como cualquier objeto hereda de Object , Object contiene los mtodos que todo tipo de objetos debera tener. Mtodos para que un objeto se clone, se compare con otro objeto y cosas por el estilo. De esta forma, si tu objeto necesita tales mtodos, pues ya los tiene definidos. Sin embargo, estos mtodos sirven para todo tipo de objetos. Por lo que no es difcil adivinar que sern todos mtodos muy generales. As que lo ms probable es que, si quieres utilizar uno de estos mtodos, tendrs que redefinirlo (override). Pero el autntico potencial de la clase Objwect no reside en su contenido, sino en el hecho de que es la superclase de toda clase Java. Y dado que ya pilotas la herencia y el casting, te dars cuenta de que cualquier objeto podr verse referenciado por una referencia de tipo Object ..Para ver un ejemplo,vamos a definir las siguientes clases: class Florero { void saludar(){ System.out.println(Soy un florero); } } class Foto { void saludar(){ System.out.println(Soy una fotografa); } } class Lampara { void saludar(){ System.out.println(Soy una lmpara); } } Bueno, pues el objetivo de nuestro programa es escribir un mtodo que meteremos en la clase Mesa (te acuerdas de ella?) que sirva para colocar cosas encima de una mesa. Recuerda la clase Mesa :
class Mesa { String color; int numPatas; String forma; static int numMesasFabricadas = 0; void setColor(String nuevoColor){ color = nuevoColor; }

void setNumPatas(int nuevoNumPatas){ numPatas = nuevoNumPatas; } void setForma(String nuevaForma){ forma = nuevaForma; } String getColor(){ return color; } String getForma(){ return forma; } int getNumPatas(){ return numPatas; } Mesa(String colorInicial, int numPatasInicial, String formaInicial){ color = colorInicial; numPatas = numPatasInicial; forma = formaInicial; numMesasFabricadas = numMesasFabricadas + 1; } Mesa() { color = azul; numPatas = 4; forma = cuadrada; numMesasFabricadas = numMesasFabricadas + 1; } int getNumMesasFabricadas() { return numMesasFabricadas; } }

Bueno, pues ahora queremos hacer un mtodo ponerEncima() para colocar encima de una mesa una lmpara, una foto o un florero, es decir, objetos de las clases que antes hemos definido. Por supuesto, el contenido del mtodo no importa en absoluto. A primera vista se nos ocurre hacer un mtodo para cada tipo de objeto a colocar, es decir, escribir un ponerEncimaUnFlorero, PonerEncimaUnaLampara, ponerEncimaUnaFoto , ms o menos as: void ponerEncimaUnFlorero (Florero nuevoFlorero) { . . . } void ponerEncimaUnaFoto (Foto nuevaFoto) { . .

. } void ponerEncimaUnaLampara(Lampara nuevaLampara) { . . . } Bueno, normal, no? Un mtodo objeto. especfico para colocar cada

Bueno, pues ahora vamos a hacer uso de la clase Object. Como es la superclase de toda clase Java, podemos hacer un mtodo que coloque cualquiera de los objetos anteriores: void ponerEncima ( Object nuevoObjeto ) { . . . } Hala. Ya podemos hacer: Mesa Margraita = new Mesa(); Florero f = new Florero(); Margarita.ponerEncima(f); Lampara l = new Lampara(); Margarita.ponerEncima(l); Hala. Revive este pequeo captulo sobre la clase Object y no sigas adelante si no has entendido a la perfeccin: CLASE OBJECT SU CONTENIDO SU USO COMO REFERENCIA GLOBAL (para toda clase Java)

Ejercicio: Plantate los siguientes fragmentos de cdigo Lampara l = new Lampara(); Margarita.ponerEncima( (Lampara) l ); Lampara l = new Lampara(); Margarita.ponerEncima( (Object) l);

Object l = new Lampara(); Margarita.ponerEncima(l); Object l = new Lampara(); Margarita.ponerEncima( (Object) l); chales un ojo de nuevo.......... aseguro: Object sabes qu es lo mejor? te crees! Que todos funcionan. Has visto lo es la clase Object ? te lo usars la clase ms de lo que t

genial

que

Vers, ahora debemos parar un minuto para reconsiderar una cosa. En el prefacio he dicho que iba a explicar todo el rollo de Java basndo me en la vida real, en ejemplos sencillos e ilustrativos, y desgraciada me nte a partir del casting ese hecho ha empeza do a decaer, y hemos alcanza do un punto en el que consideramo s mtodos ( ponerEncima() ) que ni siquiera hemos definido, slo hemos escrito su cabecera. Hay que entender que del casting en adelante es todo muy abstracto, y por ello poner ejemplos de la vida real, pues ejem.... la verdad, es complicado. Vamos, lo que pretendo hacer es disculpar me si todo esto te ha parecido demasiado tedioso, que en realidad lo es. Slo que sepas que he hecho lo que he credo mejor, hemos dejado mtodos sim implementar porque hacerlo sera complicar las cosas demasiado y no vendra a cuento; las explicaciones son ms escuetas que al principio porque la intencin es mostrar la idea limpiamente: partir de un objetivo, plantear un problema, aportar soluciones y escoger la mejor. En definitiva, si esta parte te ha parecido lo peor, siento que haya sido as, y espero y deseo de corazn que encuentres fcilmente una explicacin mejor. Por cierto, el pez, el pato y el pjaro que no tengo ni idea de cmo se llama, tambin te piden disculpas. Bueno, pues estos tres bichos tambin te animan a seguir adelante, ya que queda muy poco. De verdad. Lo prometo. Bueno, abordemos ahora un tema bastante curioso. Son las... Interfaces Vamos a ver.

El objetivo de una interface es definir qu contenidos debe tener una clase obligatoriamente. Es algo as como un contrato: una clase puede implem entar una interface si se compro mete a definir determinados contenidos. Veamos. Si yo soy un trabajador, tengo obligatoriamente que pagar impuestos. Eso significa que todo trabajador se compro mete a pagar impuestos. Bueno, debera. Las interfaces, repito, definen qu contenidos debe tener una clase. Por ejemplo, qu mtodos debe tener obligatoriamente, pero no define esos mtodos. Es decir, que una interface slo es una coleccin de cabeceras de mtodos. La clase que implemente esa interface debe implementar esos mtodos. Lo vemos con un ejemplo: Si definimos: interface Trabajador { void pagarImpuest os(); } Entonces, toda persona que sea trabajador, trabaje en lo que trabaje, debe implementar esta interface: class Funcionario implement s Trabajador { String nombre; String direccin; int edad; int sueldo; . . . void pagarImpuest os(){ System.out.println(Como funcionario, impuesto s); sueldo = sueldo (0.16*sueldo); } }

pago

mis

Hala, ahora cada funcionario pagar el 16% de su sueldo. Pero fjate, un presentador de televisin paga ms impuestos que un funcionario. Eso significa que su mtodo pagarImpuesto s() ser ligeramente diferente. Su sueldo se ve reducido en un 30%, y adems, el mensaje que nos avisa de tal pago es un poco ms pijo.

class Presentador implement s Trabajador { String nombre; int cunInsoportableSoy; . .

. void pagarImpuest os(){ System.out.println(O sea, yo pago un plusss s); sueldo = sueldo (0.30*sueldo); } } Te das cuenta? Tenemos dos personas diferentes, que nada tienen que ver la una con la otra, excepto una cosa: que ambas son trabajador as. As, deben pagar impuestos. Pero fjate que cada una lleva a cabo ese pago de forma diferente. La Interface Trabajador no determina cmo va a llevarse a cabo tal pago, solamente exige que se lleve a cabo . Bueno, creo que hasta ahora todo va ms o menos bien, no? Ahora vamos a por lo mejor de las interfaces. Lo has pillado? En realidad, el objetivo de una interface es que una clase A pueda comunicarse con otra clase B independiente me n te de cmo B est escrita. Por ejemplo: supn que ahora definimos la clase Hacienda . Esta clase exigir a todos los trabajadores que paguen sus impuestos. Pero hay miles de trabajadores distintos, unos son funcionarios, otros presentadores, pero otros son otras cosas. Sin embargo, Hacienda juega con un as en la manga: como hemos exigido que cada trabajador, sea como sea, implemente a la interface Trabajador , podemos referenciar a cualquier clase que implement e a Trabajador mediante una referencia de tipo Trabajador: class Hacienda { . . . void quePagueElCurrante(Trabajador currante) { currante.pagarImpuesto s(); } } Joer, qu cosa. Resulta que al mtodo quePagueElCurrante le pasamo s como parmetr o cualquier objeto que implemente a la interface Trabajador , y ste mtodo se encarga de hacer que pague. Te fijas? Primero: no nos importa que tipo de trabajador sea, slo nos importa que implemente a Trabajador. Segundo: La referencia a este objeto es de tipo Trabajador, no es ni Presentador ni Funcionario ni nada. El mecanismo de la referencia de tipo Trabajador es semejante a la seora Referencia que vimos en la Herencia: es una flechita que apunta slo a los contenidos de Trabajador , el resto de los contenidos ni los ve. Es como si lo nico importante de un trabajador fuese que pague impuestos.

Ahora, en un programa podemos hacer: Funcionario Fulgencio = new Funcionario(); Presentador JesusVazque z = new Funcionario(); Hacienda malditaHacienda = new Hacienda(); malditaHacienda.quePagueElCurrante( Fulgencio ); malditaHacienda.quePagueElCurrante( JesusVazque z ); Bueno, ahora, si lo has entendido todo, te preguntar s la diferencia entre Interfaces y Herencia. Bueno, esta es tal vez la mejor pregunta que puedas hacer. Cuando una clase hereda de otra, hereda las Interfaces no se definen contenidos, por lo ningn contenido. Una interface no es una superclases en la herencia, por lo que una instanciar : todos sus contenidos. En que no se puede hereda clase , como lo son las interface no se puede

Trabajador yop = new Trabajador(); / / lo peorcito. Una clase puede implementar varias interfaces a la vez, pero no puede heredar de varias clases a la vez. NO EXISTE LA (maravillosa) HERENCIA MLTIPLE EN JAVA, diga lo que diga tu profesor (vale, pero si te lo pregunta en el examen responde lo que l diga!). Las Interfaces pueden parecer un mecanismo de herencia mltiple, pero no es as en realidad. Supongo que tu profesor de dar ms razones para diferenciar interfaces de herencia. Yo slo te digo las ms representativas (para m). Hala. Repasa los conceptos de HERENCIA (ea, fastidiate) INTERFACE USO DE IMPLEMENTS USO DE REFERENCIAS DEL TIPO DE UNA INTERFACE DIFERENCIAS ENTRE HERENCIA E INTERFACES Te doy una sorpresa? Ya hemos acabado. Eplogo Es una pena, me gusta pensar en un eplogo como en el final de un libro de aventuras y no de un cursillo rpido de OOP y Java. Hemos visto cmo es la estructura de la OOP: clases y objetos. Hemos visto cmo se llevan a cabo en Java. Hemos visto programacin

estructur a da, es decir, sentencias de control: bucles y sentencias condicionales, la fatal historia de la recursividad, herencia, casting, interfaces.... y poco ms. Desgraciada mente hay otros puntos que no he tocado, porque realmente son un tanto innecesarios porque ocuparan un hueco que no es necesario hacer: clases abstractas, tipos bsicos de datos, clases para acceso a disco (los asquerosos flujos o streams), la estpida BufferedString.... en fin, unas cuantas cosas que no son realmente necesarias: tu profesor te las ensear durante tres horas cada una de ellas, cuando no son necesarios ms de diez minutos. Por qu estas lagunas? Muy sencillo: porque mi intencin no es ensearte Java a fondo, (eso lo har el mastering Java se la editorial SUN) sino ensearte a programar en OOP. Y eso? Fcil: si sabes programar, entenders cualquier cosa fcilmente. Cuando hayas ledo todo este mamotreto de letras y dibujos, y cuando lo entiendas a la perfeccin, no te costrar aprender a usar flujos de entrada y salida en disco, manejo de excepciones, acceso restringido a miembros de clase, o yo qu s. Es decir, que aprendas primero a caminar... para luego echar a correr. Tal vez algn da escribas t la segunda parte de Java para aprobar explicando todo lo que me he dejado atrs. Sera muy bonito. Si quieres, te paso los JPG del pez, el pato y el pajaro ese que no s cmo se llama. Bueno, aqu acabamos. Espero que no se te haya hecho muy tedioso (jeeee, que iluso soy). Psalo bien, estudia mucho, pregunta lo que quieras y scale partido a todo esto, vale? David Muoz Daz Grupo de Usuarios de Linux de la Universidad Carlos III de Madrid gul@gul.uc3m.es

The Stone Soup Story Once upon a time, somewhere in Eastern Europe, there was a great famine.

People jealously hoarded whatever food they could find, hiding it even from their friends and neighbors. One day a peddler drove his wagon into a village, sold a few of his wares, and began asking questions as if he planned to stay for the night. "There's not a bite to eat in the whole province," he was told. "Better keep moving on." "Oh, I have everything I need," he said. "In fact, I was thinking of making some stone soup to share with all of you." He pulled an iron cauldron from his wagon, filled it with water, and built a fire under it. Then, with great ceremo ny, he drew an ordinary - looking stone from a velvet bag and droppe d it into the water. By now, hearing the rumor of food, most of the villagers had come to the square or watched from their windows. As the peddler sniffed the "broth" and licked his lips in anticipation, hunger began to overcome their skepticism. "Ahh," the peddler said to himself rather loudly, "I do like a tasty stone soup. Of course, stone soup with CABBAGE - - that's hard to beat." Soon a villager approached hesitantly, holding a cabbage he'd retrieved from its hiding place, and added it to the pot. "Capital!" cried the peddler. "You know, I once had stone soup with cabbage and a bit of salt beef as well, and it was fit for a king." The village butcher managed to find some salt beef...and so it went, through potatoes, onions, carrots, mushroo m s, and so on, until there was indeed a delicious meal for all. The villagers offered the peddler a great deal of money for the magic stone, but he refused to sell and traveled on the next day. And from that time on, long after the famine had ended, they reminisced about the finest soup they'd ever had.
(tomado de un document o de Monte Davis)

You might also like