• No se han encontrado resultados

El ejemplo de los marcianos con paquetes

In document Tutorial básico de Java (página 77-86)

En esta sección vamos a reorganizar el código de la guerra entre marcianos y terrícolas para emplear paquetes. La principal funcionalidad de los paquetes es precisamente ayudar a organizar programas complejos. El cómo organizar un código en paquetes depende completamente del propósito de dicho código y de cómo se quiera diseñar el software. Con el tiempo irás ganando experiencia e irás aprendiendo a organizar tus clases en paquetes de modo adecuado.

Para un ejemplo tan trivial como éste podría perfectamente argumentarse que con emplear un único paquete es más que suficiente. No obstante, vamos a reorganizar el código empleando tres paquetes. Uno de los paquetes lo llamaremos "seres" porque en él será donde vayan todos los objetos del universo que consideramos "seres". En nuestro caso, irán Marciano, Terrícola, Guerrero y SerVivo. Crearemos un segundo paquete llamado "máquinas" donde irían todas las máquinas que implementásemos. En nuestro caso, la única máquina en el problema es Nave. Por último, creamos un paquete "auxiliar" en la cual colocamos la clase que contiene el método main.

Los únicos cambios que será necesario hacer en el código es incluir las sentencias que indican a qué paquete pertenece cada clase, colocar cada clase en el directorio adecuado y, cuando una clase emplee clases de otros paquetes diferentes al suyo, añadir la sentencia import correspondiente. Aunque a continuación vamos a mostrar el código fuente del ejemplo modificado, recomiendo al lector que, a modo de ejercicio, coja el código que ya conoce (el que podrá encontrar en el directorio "Guerra") e intente realizar las transformaciones que he descrito. El código modificado se encuentra en el directorio "GuerraconPaquetes".

Y el código fuente (última oportunidad para abandonar los apuntes e intentar realizar los cambios por tu cuenta sin antes mirar) es:

package seres;

//No necesitamos importar nada porque no usamos clases de otros paquetes

public abstract class SerVivo {

public boolean isVivo(){ return vivo;

}

protected boolean vivo = true; }

package seres;

//No necesitamos importar nada porque no usamos clases de otros paquetes

public abstract class Guerrero extends SerVivo {

public Guerrero (String soy){ blanco = generaBlanco(); this.soy = soy;

}

public int dispara (){ if (vivo){

int disparo = ((int)(Math.random()*10));

System.out.println(soy + "Dispara nº " +disparo);

return disparo; }

else

return 100; }

public int getBlanco(){ return blanco; }

private int generaBlanco (){

return ((int)(Math.random()*10)); }

protected int blanco; private final String soy; }

package seres;

//No necesitamos importar nada porque no usamos clases de otros paquetes

public class Terricola extends Guerrero {

//ahora el constructor tiene que ser público para el clases de otros

//paquetes que no hereden ésta (Nave) puedan crear instancias de Terricola

public Terricola(String soy){ super(soy);

total++;

this.soy= soy; }

public void recibeDisparo(int i){

if (vivo && blanco == i){ vivo = false;

total--;

System.out.println (soy + " Muerto por disparo nº " +i);

} }

public int getTotal(){ return total; }

private static int total = 0; private String soy;

}

package seres;

//No necesitamos importar nada porque no usamos clases de otros paquetes

public class Marciano extends Guerrero {

//ahora el constructor tiene que ser público para el clases de otros

//paquetes que no hereden ésta (Nave) puedan crear instancias de Marciano

public Marciano(String soy){ super(soy); this.soy =soy; total++; }

public void recibeDisparo(int i){ if (vivo && blanco == i){ vivo = false;

System.out.println (soy + "Muerto por disparo nº " +i);

} }

public int getTotal(){ return total; }

private static int total = 0; private String soy;

}

package maquinas;

//necesitamos emplear clases del paquete seres import seres.*;

public class Nave {

public Nave (String somos){ this.somos = somos;

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

if (somos.equals("Terricolas")){

tripulacion [i] = new Terricola(somos); }

else{

tripulacion [i] = new Marciano(somos);

} }

System.out.println("Creada nave de " + somos); }

public void recibeDisparo(int i){ for (int j=0; j<10;j++){

((Terricola)(tripulacion[j])).recibeDisparo(i); } else{ ((Marciano)(tripulacion[j])).recibeDisparo(i); } } }

public int generaDisparo(int i){ return tripulacion[i].dispara(); }

public int cuantosQuedan(){

if (somos.equals("Terricolas")){ return ((Terricola)(tripulacion[1])).getTotal(); } else{ return ((Marciano)(tripulacion[1])).getTotal(); } }

private Guerrero[] tripulacion = new Guerrero[10]; private String somos;

}

package auxiliar;

//necesitamos emplear la clase Nave import maquinas.*;

public class Guerra { public Guerra(){

nave1 = new Nave("Terricolas"); nave2 = new Nave("Marcianos");

empiezaGuerra(); }

public void empiezaGuerra(){ do{ for(int i = 0; i<10;i++){ nave2.recibeDisparo(nave1.generaDisparo(i)); nave1.recibeDisparo(nave2.generaDisparo(i)); } }while(nave1.cuantosQuedan()>0&&nave2.cuantosQuedan()>0); if(nave1.cuantosQuedan()>0){ System.out.println("GANARON LOS TERRICOLAS!!!!!"); } else if (nave2.cuantosQuedan()>0){

System.out.println("GANARON LOS MARCIANOS"); }

}

public static void main(String[] args){ new Guerra();

}

private Nave nave1, nave2; }

6

PROGRAMACIÓN GRÁFICA CON SWING

El objetivo de este tema es enseñar a diseñar pequeñas interfaces gráficas empleando para ello las librerías gráficas Swing. Una interfaz es lo que le permite a un usuario comunicarse con un programa, una interfaz es lo que nosotros vemos al arrancar, por ejemplo, un navegador de internet: un conjunto de menús, botones, barras.... que nos permiten activar un código que es el que realmente nos llevará a una página web, salvará la imagen en el disco duro....

Las librerías gráficas que usaremos vienen a sustituir a las antiguas AWT. Las nuevas librerías a parte de tener una mayor cantidad de opciones sobre los componentes (como distintas apariencias, control sobre el focus, mayor número de campos que modifican su aspecto, mayor facilidad para pintar al hacer el buffering transparente al usuario....) se diferencian de las anteriores radicalmente en su implementación.

En AWT cuando añadíamos un botón, por ejemplo, a nuestro diseño el compilador generaba código que le pedía al sistema operativo la creación de un botón en un determinado sitio con unas determinadas propiedades; en Swing ya no se pide al sistema operativo nada: se dibuja el botón sobre la ventana en la que lo queríamos. Con esto se eliminaron muchos problemas que existían antes con los códigos de las interfaces gráficas, que debido a depender del sistema operativo para obtener sus componentes gráficos, era necesario testar los programas en distintos sistemas operativos, pudiendo tener distintos bugs en cada uno de ellos.

Esto evidentemente iba en contra de la filosofía de Java, supuestamente un lenguaje que no dependía de la plataforma. Con Swing se mejoró bastante este aspecto: lo único que se pide al sistema operativa es una ventana, una vez que tenemos la ventana dibujamos botones, listas, scroll-bars... y todo lo que necesitemos sobre ella. Evidentemente esta aproximación gana mucho en lo que a independencia de la plataforma se refiere. Además el hecho de que el botón no sea un botón del S.O. sino un botón pintado por Java nos da un mayor control sobre su apariencia.

In document Tutorial básico de Java (página 77-86)