Estructuras de selección, repetición, salto, continúe, Creación de

Anuncio
5 – Estructuras de selección, repetición, salto, continúe, Creación de
objetos (Instancias), Paquetes y Visibilidad.
Programación Orientada a Objetos
Proyecto Curricular de Ingeniería de Sistemas
Descripción de las estructuras de programación, de tipo bifurcación
o toma de decisiones, en Java.
Se tratan de las mismas estructuras que pueden encontrarse en cualquier otro
lenguaje, si sabes ya programar ten en cuenta que lo único que necesitas aprender es
la sintaxis y eso se consigue mucho mejor programando así que puedes pasar por alto
este punto.
Bifurcaciones: Permiten ejecutar código en función de una expresión evaluada
Bifurcaciones if:
Tienen las siguientes posibilidades en su sintaxis:
if (ExpresionBooleana){conjuntoDeSentencias}
if (ExpresionBooleana) {conjuntoDeSentencias}
else {conjuntoAlternativo}
if (ExpresionBooleana) {conjuntoDeSentencias}
else if {conjuntoAlternativo}
else if {conjuntoAlternativo2}
Ejemplos:
public class prueba {
public static void main (String args[]){
int i=5;
if (i == 5){ System.out.println(" i vale 5 ");}
else {System.out.println("i no vale 5");}
i=4;
if (i == 5){ System.out.println(" i vale 5 ");}
else if (i < 5){System.out.println("i es menor que 5");}
else if (i > 5){System.out.println("i es mayor que 5");}
}
}
Bifurcaciones switch
Son las que permiten realizar varias acciones distintas dependiendo del estado de una
variable.
Switch (Expresion){
Case valor1: conjuntoDeSentencias;
break;
Case valor2: SentenciasAlternativas;
break;
Case valor3: SentenciasAlternativas2;
break;
Case valor4: SentenciasAlternativas3;
break;
}
La sentencia 'break' detrás de cada opción de case sirve para que no evalue el resto
de opciones sino que se salga directamente del 'Switch', asi que dependiendo de lo
que quieras hacer la pondrás o no, recuerde que break rompe y la sentencia continué
se emplea cuando ninguna de los case se hace.
Ejemplos:
public class prueba {
public static void main (String args[]){
char i ='2';
switch (i) {
case '1': System.out.println( "i contiene un 1"); break;
case '2': System.out.println( "i contiene un 2"); break;
case '3': System.out.println( "i contiene un 3"); break;
default : System.out.println( "i no es 1, 2 ó 3 ");
}
}
}
Vemos los bucles for, while y do while, junto con otras estructuras
de programación como break, continue y return.
Los bucles se utilizan para ejecutar un conjunto de instrucciones varias
veces basándose siempre en una condición que decidirá si se sigue
repitiendo o no. Veamos los tipos que hay.
Bucle While
while (expresion) {sentencias}
Las instrucciones dentro de las llaves se ejecutan mientras la expresión sea
verdadera.
public class prueba {
public static void main (String args[]){
int i=5;
while ( i > 0 ) {i --;}
//
las llaves aquí se podían haber omitido, puesto
//
que solo hay una sentencia.
System.out.println("Ahora i vale 0");
}
}
Bucle For
Es un bucle más "fijo", permite ejecutar el conjunto de sentencias un
numero determinado de veces fijado al principio del bucle y funciona por
tanto como un contador. Su expresión general seria como la que sigue:
for (inicialización, expresionBooleana, incremento)
{conjuntoDeSentencias;}
public class prueba {
public static void main (String args[]){
for (int i= 0; i <10; i++){
System.out.println("el valor de i es: " + i);
}
}
}
Este ejemplo nos mostraría por la pantalla diez líneas diciéndonos el valor
creciente de 'i' de cero a nueve.
Bucle do while
Es igual al bucle while anteriormente visto, solo que ahora se evalúa la
expresión al final del bucle, por lo que ese conjunto de sentencias se
ejecuta al menos una vez:
public class prueba {
public static void main (String args[]){
int i=5;
do
{i --;} // las llaves aquí se pueden omitir puesto
while ( i > 0 ); // que solo hay una sentencia.
}
}
Este ejemplo similar al anterior para el bucle while se diferencia en que
ejecuta una vez mas las sentencias en su cuerpo puesto que comprueba la
condición posteriormente.
Sentencias Break, Continue y Return
Antes hemos hablado de la sentencia Break con las bifurcaciones switch.
Pues bien, esta sentencia tiene un valor mas amplio. La sentencia break
nos permite salirnos del bloque de sentencias (encerrado entre llaves) o el
bucle que estamos ejecutando, sin ejecutar las sentencias que resten para
el final o las restantes iteraciones del bucle. Por ejemplo:
public class prueba {
public static void main (String args[]){
int i=5;
do{
i --;
if (i == 3) break;
} while ( i > 0 );
//
En este ejemplo cuando i tenga el valor 3
//
se abandonará el bucle.
}
}
La sentencia Continue solo es válida para bucles, sirve para no ejecutar las
sentencias que restan para la finalización de una iteración de ese bucle,
continuando después con las siguientes iteraciones del bucle. Por ejemplo:
public class prueba {
public static void main (String args[]){
int i=5;
do{
if (i == 3) continue;
i --;
}while ( i > 0 ); // En este ejemplo cuando i tenga el valor 3
//
se abandonará la iteración y por tanto el
//
bucle no tendrá fin puesto que no se
//
ejecutaría la sentencia de decremento.
}
}
Tanto la sentencia continue como break se pueden utilizar con etiquetas
para poder discriminar los bucles que quieren afectar en caso de que se
encuentren en un bucle anidado. Por ejemplo:
public class prueba {
public static void main (String args[]){
bucle1:
for (int i=0; i<10; i++){
bucle2:{
System.out.println("i="+i+" Bucle 2");
for (int j=0; i<10; j++){
System.out.println("j="+j+" Bucle 2");
if (j==5) {
System.out.println("si j=5 del Bucle 2");
break bucle2;
//break bucle1;
}//cierra if
}//cierra for del j
}//cierra bucle2
} // cuando j llega a 5 el bucle2 deja de
// ejecutarse hasta la siguiente iteracion
// del bloque1
}
}
Por último vemos la sentencia return. Esta sentencia nos permite finalizar
también un conjunto de sentencias, con la peculiaridad esta vez de que
también finaliza el método o función que en el que se encuentre. En el caso
de que queramos devolver un valor desde esa función o método lo debemos
poner a continuación de return. Por ejemplo:
public static void main(String[] args) {
System.out.print(funcionEjemplo());
}
static int funcionEjemplo(){
int i=0;
while (i < 100){
i++;
return i;
// Cunado encuatra un return retorna este valor y termina el metodo
//este absurdo metodo nos devuelve 1 como puedes comprobar
}
//Nunca se llega a este punto ya que al encontrar el 1er return
//el metodo termina
imprimir();
//Siempre que un metodo devuelva algo, la ultima sentecia en la
//declaracion debe ser el return, de lo contrario marca error.
return i;
}
static void imprimir (){
System.out.println("esto no se imprime");
}
}
}
Bloque Try – Catch – Finally
Se trata de unas sentencias de control relacionadas con el tratamiento de
excepciones, no tiene nada que ver con las estructuras de control de bucle,
vistas en este capitulo, salvo porque es también una estructura de control.
La comentamos a continuación, aunque se verá con ejemplos más adelante.
El tratamiento de excepciones se utiliza para detectar errores cuando se
ejecutan nuestros programas y tratarlos del modo que nosotros queramos.
Los errores cazados por un sistema de tratamiento de excepciones no
bloquean el programa y el manejo de excepciones nos permite hacer cosas
cuando esos errores ocurren.
Por ahora solo es bueno que sepas que existen, ya las veremos en otro
momento.
Seguimos explorando el lenguaje de programación Java, esta vez
introduciendo el trabajo con objetos y las partes de un programa
típico orientado a objetos y escrito en Java.
Vamos a intentar entender como funciona un programa en Java para poder
empezar a programar nosotros posteriormente. se intentara también
explicar algo sobre los conceptos básicos de la Programación orientada a
objetos, mientras avanzamos. Seguramente en un futuro ampliaremos los
contenidos sobre programación orientada a objetos dentro de el contenido
de la materia por la importancia que esta tiene. Vamos adelante.
Estructura básica de un programa en Java
En Java, como en cualquier otro lenguaje orientado a objetos,
abandonamos el modo de entender un programa que utilizábamos
anteriormente para aproximarnos a un modo más cercano a "la vida
misma".
Los programas ahora estarán divididos en clases. Una clase en si se puede
entender como un programa independiente, tiene sus propios datos y
también maneja esos datos "a su modo".
La relación con la vida misma la podemos ver en el siguiente comentario:
Imaginemos que dos clases tal y como las hemos explicado anteriormente
son "la clase mecánico" y la "clase panadero". Cada una de estas clases
tiene sus propias herramientas y sus propias tareas, por ejemplo, el
panadero tiene "harina" y una de sus tareas es "amasar", mientras que el
mecánico tiene "bujías" y una de sus tareas es "limpiar bujías". Lo
importante de todo esto es que cada uno hace muy bien su tarea pero no
tiene sentido "llevar el coche a la panadería de la esquina" ni "pedir una
Alineado de $500 junto con un cambio de aceite".
Vamos a estudiar unas pequeñas clases que nos servirán en un futuro para
implementar un ejercicio un poco más complicado. Estas clases son la clase
"ficha" y la clase "tablero" que nos servirán para implementar con el tiempo
un juego de las "cuatro en raya".
public class Fichas {
String color;
public Fichas(String c){color=c;}
public String dameColor(){return(color);}
}
Esta va a ser la clase ficha. Veámosla un poco: Esta clase tiene una variable "color"
que es un String. El tipo String no es un tipo primitivo en Java, es una clase que está
dentro del API de Java, mas concretamente dentro del paquete "Java.lang" y que
además siempre se incluye por defecto en cada programa Java que hagamos.
Por tanto, lo que estamos haciendo en la segunda línea de nuestro programa es
declarar un objeto sin valor de la clase String.
La tercera y la cuarta línea son dos métodos de la clase "Fichas" que estamos
definiendo.
El primer método es un constructor. Un constructor es un método que se llama con la
sentencia "new", es decir cuando alguien quiera crear un objeto y que nos define bajo
que condiciones se crea ese objeto, ya lo entenderás mejor. En este caso para que
alguien quiera crear una ficha tiene que pasar un objeto "String" como parámetro y
obtendrá a cambio un objeto de la clase "Fichas" del color que ha solicitado.
El segundo método nos devuelve un objeto "String" con el valor del color que tiene el
objeto ficha en ese momento.
public class Tablero {
Fichas estadoTablero[][];
public Tablero(){estadoTablero=new Fichas [6][7];};
public boolean verSiLlena(int índice){
return(estadoTablero[7][indice]==null);};
}
Bueno, esta segunda clase que estudiamos tiene también un objeto interno
llamado "estadoTablero" que en este caso es un "arreglo" cuyas posiciones
son de la clase anteriormente declarada "Fichas".
También tenemos un "constructor" para el objeto "estadoTablero" que crea
ese "arreglo" con las dimensiones que queremos.
Y en este caso hay una función que nos dice si la columna por la que nos
interesamos con el parámetro de entrada "índice" está llena.
De estos dos ejemplos de clases aún nos quedan algunos conceptos por
aprender, como por ejemplo eso del "constructor". Lo veremos con
detenimiento más adelante.
Vemos lo que son las clases, cómo crearlas y algunos detalles
adicionales de su uso.
En si, y como se ha comentado anteriormente en las guías anteriores, las
clases marcan la estructura básica de un programa tanto en Java como en
la programación orientada a objetos en general.
Una clase es el producto de enfocar la programación a los datos más que a
las funciones. Por tanto una clase es una colección de datos y además para
operar con ellos una serie de funciones propias de la clase. Veamos por
ejemplo la clase "Fichas" definida anteriormente, su único dato es "el color"
y la única operación que permite es saber el color de la ficha en cualquier
momento. Eso permite un acceso restrictivo a los datos según la función de
los mismos. En este caso la clase es así basándose en la vida misma: No
creo que nadie haya cambiado el color de una ficha jugando a las "cuatro
en raya" y en caso positivo no tendría muy buenas intenciones al hacerlo.
Además de este método básico de protección de los datos, Java permite
algunos más que vemos ahora mismo.
Cuando declaramos una clase lo primero que ponemos es la cabecera:
public class Fichas { (cuerpo de la clase) }
La primera palabra nos proporciona la posibilidad de dar permisos de
accesos a nuestra clase, los permisos son los siguientes:
•
•
"Public": Una clase "public" es accesible desde cualquier otra clase,
no obstante para que esto suceda debe ser primero accesible el
"package" de esa clase "public". Para que un "package" sea
accesible debe de estar en el directorio que señala la variable
"CLASSPATH" que definimos al instalar nuestro entorno Java y, claro
está, tener permiso de lectura en ese directorio.
"Package": Usar este identificador en la cabecera de la clase es
opcional, pues es la opción por defecto en java, es decir, si
escribimos:
class Fichas {(Cuerpo de la clase)}
Es lo mismo que si escribimos:
package class Fichas {(Cuerpo de la clase)}
Las clases "package" ( que podemos entender como las que no son "public"
) son accesibles solo desde su propio package.
Esto es relativo a la accesibilidad de las clases. Más conceptos relativos a la
accesibilidad hacen referencia a los atributos internos de una clase que ya
comentamos en sesión anterior, y a sus métodos.
En cuanto al nombre de la clase consideraremos varias cosas. Debe de
obedecer al convenio de nombres de Java y coincidir con el nombre del
fichero ".java" en el que se guardará la clase.
Lo normal es que cada clase vaya incluida en un único fichero pero claro
está, nos puede interesar por algún motivo meter varias clases en un único
fichero. En este caso solo puede haber una clase public que es la que dará
el nombre a dicho fichero. En caso de que no hubiese una clase public el
compilador entenderá que la clase "principal" de ese fichero es la que
concuerda con el nombre del mismo, por lo que evidentemente dos clases
con un mismo nombre no son permitidas en un mismo fichero.
Por último para explicar la estructura de una clase se explicaran los
elementos habituales en la definición de su cuerpo.
Primero se suelen declarar, al menos, las variables internas de esa clase y
posteriormente se definen los constructores y los métodos que dispondrá la
clase. Lo entenderemos mejor más adelante
En la definición de constructores y métodos tenemos que tener en cuenta
un nuevo concepto de la programación orientada a objetos. La sobrecarga.
La sobrecarga consiste en poder tener varios métodos o constructores con
el mismo nombre dentro de una misma clase y que no hagan las mismas
cosas.
Esto se consigue de una manera muy sencilla, se diferencian entre ellos
mediante el número y tipo de parámetros que reciben. Veamos un ejemplo:
/*tenemos dos métodos que pueden por ejemplo obtener el área de una figura geométrica en
concreto, podrían ser:*/
float obtenerAreaCirculo(Circulo ci){
/* ... */
}
float obtenerAreaCuadrado(Cuadrado cu){
/* ... */
}
/*en Java esto se puede abreviar teniendo dos métodos sobrecargados, por ejemplo: */
float obtenerArea(Circulo ci){
/* ... */
}
float obtenerArea(Cuadrado cu){
/* ... */
}
/*A la hora de ejecutar el método obtenerArea se utilizará el que corresponda al parámetro
que se le pase por cabecera*/
Java permite organizar las clases mediante agrupaciones o
packages.
Efectivamente vamos a necesitar organizar nuestras clases en algún
momento porque nuestro desarrollo puede ir creciendo, y tener un cúmulo
de clases todas juntas en un directorio, sin ningún tipo de organización
física ni lógica, no nos ayudará demasiado.
Java nos permite con los "Packages" evitar esta situación de un modo
bastante elegante y ordenado. Un "Package" es básicamente una
agrupación de clases, vemos por ejemplo que la versión 1.2 de Java incluye
un total de 59 "Packages" para organizar todo su API, la versión del JDK 1.5
posee 165 packages.
Cualquier grupo de clases se puede organizar dentro de un "package" pero
evidentemente lo más normal es que tus clases las organices por algún
motivo. Las clases se suelen organizar según la relación entre ellas. Por
ejemplo si tuviésemos un grupo de clases que permiten hacer una
ordenación de elementos en un arreglo podríamos organizarlas de este
modo:
Quicksort.class; // Clase para ordenar arreglos con el método quicksort
Burbuja.class; // Clase para ordenar arreglos con el método de la burbuja
Seleccion.class; // Clase para ordenar arreglos con el método de selección
Insercion.class; // Clase para ordenar arreglos con el método de inserción directa
/* Podemos englobar estas clases en un package puesto que todas están relacionadas en su
cometido. Crearemos por tanto el "package ordenaciones" para que podamos acceder a ellas
de este modo: */
ordenacion.Quicksort.class; // Ejemplo acceso a quicksort en el package ordenación
/* Igualmente podríamos tener también clases para la búsqueda de un elemento en un arreglo
en tal caso repetiríamos el proceso y por ejemplo tendríamos el "package tratamientoArreglos"
de este modo: */
tratamientoArreglos.ordenacion.Quicksort.class; // Ejemplo acceso a quicksort dentro del //
package ordenación que a su vez está // dentro del package tratamientoArreglos.
El uso de "Packages" no solo nos permite organizar nuestras clases, sino
que nos permite diferenciar clases que siendo distintas tengan que tener el
mismo nombre, es decir, ayuda a java con la resolución de nombres.
También como hemos visto por encima anteriormente nos permite ciertas
normas para controlar el acceso a clases.
Veamos ahora como utilizar los "packages" para nuestras clases. Lo
primero que tenemos que tener en cuenta es que todas las clases que van
a pertenecer a un mismo "package" tienen que estar en un mismo
directorio que debe coincidir en nombre con el nombre del "package".
Vemos que por tanto el nombre completo de una clase de un "package"
equivale a su ruta desde el directorio que tomemos de base para nuestras
clases.
El convenio de nombres de Java establece también que los nombres de los
"packages" empiecen por minúsculas.
En segundo lugar para utilizar los "packages" en nuestras clases tenemos
que incluir al principio del fichero de la clase (antes de cualquier otra
sentencia) la linea:
Package nombreDelPackage;
Por último veamos la sentencia "import". "import" permite importar un
"package" a nuestra clase Java. Esto nos permite acceder (en caso de que
sean accesibles) sin usar todo el nombre del "package" a cualquier clase
dentro de él. Veámoslo en el siguiente ejemplo:
Import tratamientoArreglos.ordenación.*; //Importamos todas las clases
//del "Package" de ordenación de
//arreglos que teníamos organizado.
/*tiramos líneas de código en Java hasta que... */
Quicksort arregloQuick= new Quicksort(); //... En cualquier momento de nuestra clase
// podemos hacer uso de la clase Quicksort sin
// utilizar toda la ruta del package.
Hay que tener también en cuenta que importando un "package" no
importamos todos sus "subpackages" sino solo todas las clases de ese
"package". También podemos simplemente importar solo una clase dentro
de ese "package" poniendo en vez de un asterisco el nombre de la clase a
importar.
Para acabar con este punto se realizara el siguiente comentario acerca del
API de Java. Ya se ha dicho que las clases del API de Java están
organizadas en "packages" según su función. Hay "packages" preparados
para acometer las mas variadas tareas. Es ejercicio del lector informarse de
que "packages" le interesan en su desarrollo y del funcionamiento de las
clases incluidas en estos. Nosotros veremos ciertos "packages" de uso
habitual durante el curso.
Como ya se comento, en java no se empieza desde cero, tenemos un
conjunto de clases que podemos incluir en nuestro programa sin necesidad
de importar ningún "package". Esas clases son las que pertenecen al
"package" Java.lang. este "package" incluye las clases básicas de Java
como por ejemplo la clase "Arreglo" que utilizaremos muy habitualmente.
Ejercicio practico para el Lector:
Empleando el IDE de desarrollo eclipse y las ventajas que este ofrece en la
creación de clases y paquetes cree el siguiente proyecto y pruébelo,
verifique a trabes del explorador de su sistema operativo el contenido de
los paquetes creados y se fijara que son carpetas.
Estructura en el explorar del paquetes del proyecto a crear
A continuación se anexa el codigo de las clases Globo y JugarGloba para
que sean implementadas y probadas en el IDE de desarrollo Eclipse.
//Paquete objeto que contiene la clase Globo
package objeto;
import java.awt.*;
public class Globo{
private int diametro;
private int xCoord, yCoord;
public Globo (int diametroInicial, int xInicial, int
yInicial) {
diametro = diametroInicial;
xCoord = xInicial;
yCoord = yInicial;
}
public void cambiarTamaño (int cambio) {
diametro = diametro + cambio;
}
public void mostrar (Graphics g) {
g.drawOval (xCoord, yCoord, diametro, diametro);
}
}
//Paquete principal que contiene la clase JugarGlobo
package principal;
import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;
import javax.swing.JFrame;
import objeto.Globo;
public class JugarGlobo extends Applet
implements ActionListener {
private Button agrandar, reducir;
private Globo miGlobo;
public void init() {
agrandar = new Button ("Agrandar");
add (agrandar);
agrandar.addActionListener(this);
reducir = new Button ("Reducir");
add (reducir);
reducir.addActionListener(this);
miGlobo = new Globo (20, 50, 50);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == agrandar)
miGlobo.cambiarTamaño(10);
if (event.getSource() == reducir)
miGlobo.cambiarTamaño(-10);
repaint();
}
public void paint (Graphics g) {
miGlobo.mostrar(g);
}
public static void main (String Args[]){
JFrame f = new JFrame("Applet desde Consola");
//crear una instancia de JugarGlobo
JugarGlobo start = new JugarGlobo();
//Agregar la instancia del applet al marco
f.add(start);
//inicializar las variables al ancho y el alto de la
tag <applet>
int width = 400;
int height = 400;
f.setSize(width, height);
//llamar a init() y a start() si es necesario
start.init();
//hacer visible el marco
f.show();
}
}
Descargar