viernes, 29 de octubre de 2010

Leer y Escribir un fichero de texto

En java tenemos muchas posibilidades para leer y escribir ficheros de texto, binarios, con formato xml, etc, etc. En este tutorial nos vamos a centrar en escribir y leer ficheros de texto llano. Vermos también la clase JFileChooser que permite mostar una ventana para que el usuario navegue por los directorios y elija un fichero. No nos meteremos en profunidades, sólo lo básico para empezar a escribir y leer ficheros.


La clase JFileChooser

Siguiendo con nuestro editor de textos sencillo, dos de las acciones que debemos implementar en nuestro menú son las de salvar el texto en fichero y leer el texto de un fichero. En ambos casos hay que darle oportunidad al usuario de elegir el fichero bien para salvar, bien para leer.

La clase JFileChooser muestra directamente una ventana que permite navegar por los directorios y elegir un fichero. Un uso simple de esta clase es realmente sencillo.

Para pedir un fichero para abrirlo y leerlo basta hacer dos líneas de código

JFileChooser fileChooser = new JFileChooser();
int seleccion = fileChooser.showOpenDialog(areaTexto);

Veremos el parámetro areaTexto un poco más abajo. Por lo demás, listo, esto abre una ventana para navegar por los directorios y elegir un fichero similar a la de la figura

JFileChooser

Cuando el usuario termine, pulsará "Abrir" o "Cancelar". En el entero seleccion se nos guardará el botón que ha apretado. Sólo debemos comprobar si es el botón de "Abrir" para pedirle al JFileChooser qué fichero ha elegido el usuario y empezar a trabajar con él.

if (seleccion == JFileChooser.APPROVE_OPTION)
{
File fichero = fileChooser.getSelectedFile();
// y a trabajar con fichero ....
}

Si seleccion vale JFileChooser.APPROVE_OPTION es que el usuario ha pulsado "Abrir", así que pedimos el fichero seleccionado con getSelectedFile() y ... ¡¡¡ a trabajar !!!

Vale, vale, pero ¿qué es eso de pasarle el areaTexto en el parámetro?. La explicación es simple. JFileChooser abre una ventana que se mostrará junto a la ventana de nuestro editor. Nos gustaría que esta ventana de selección de fichero no se vaya detrás y quede oculta por la ventana del editor. La ventana de elegir fichero debería estar siempre delante y visible sobre el editor. La forma de conseguir esto es que JFileChooser sepa cual es esta ventana delante de la cual debe estar siempre. Para saber cual es esa ventana, basta con pasarle en el parámetro cualquier componente de dicha ventana. En nuestro ejemplo hemos decidido pasarle el JTextArea de nuestro editor, pero podíamos pasarle perfectamente el JMenuBar o el JFrame principal.

El JTextArea es una buena elección por un segundo motivo. Este código estará en las acciones de salvar y cargar texto de un fichero. El texto que se va a guardar o el que se lea se cojerá o meterá en el JTextArea. La clase AccionSalvar y AccionCargar deben tener accesible el JTextArea para leer de él el texto que tienen que guardar en fichero o para meter en él el texto que han leido del fichero. Puesto que tienen que tener el JTextArea de todas maneras, lo usaremos como parámetro del JFileChooser.

Para elegir un fichero para salvar, el código es exactamente igual, pero cambia el método para visualizar el diálogo.

JFileChooser fileChooser = new JFileChooser();
int seleccion = fileChooser.showSaveDialog(areaTexto);

La única diferencia es que cambia la etiqueta del botón "Abrir" por "Guardar".

Escribir un fichero de texto

Una vez elegido el fichero en el que queremos salvar el texto, simplemente debemos abrir el fichero para escritura y emepezar a escribir.

En java tenemos muchas clases y variantes para escribir ficheros: PrintStream, FileWriter, FileOutputStream, etc, etc. Todas hacen lo mismo, escribir en un fichero. La diferencia entre ellas suelen ser los métodos que tienen para escribir en el fichero o algunos aspectos internos, como si usan buffer o no. Algunas de ellas sólo tienen métodos para escribir bytes, otras permiten escribir String, etc, etc. Para elegir una de ellas, simplemente hay que ver qué tenemos, un File en nuestro caso y qué necesitamos, en nuestro caso algún método que nos permita escribir String.

Por supuesto, esta forma de elegir es muy tonta, pero nos vale para nuestro ejemplo. Si queremos "darle caña" al fichero escribiendo mucho y muy seguido quizás sea mejor pensar en qué clases son más eficientes en vez de en limitarnos a si tiene o no un método que nos resulte cómodo. Sin embargo, esto es tema para otro tutorial.

Para escribir fichero de texto llano a partir de un File, que es el que nos proporciona la clase JFileChooser, una clase ideal es PrintWriter. Simplemente con el siguiente código tenemos todo hecho

PrintWriter writer = new PrintWriter(fichero);
writer.print(areaTexto.getText());
writer.close();

Abrimos el fichero haciendo un new PrintWriter(), con print() escribimos el texto obtenido de areaTexto.getText() y cerramos el fichero.

PrintWriter tiene además muchos métodos que permiten escribir en formato texto llano números, cadenas, etc.

Leer un fichero

Para leer un fichero nos pasa algo parecido. Tenemos un montón de clases que leen ficheros FileInputStream, FileReader, InputStreamReader, BufferedReader. Igual que al escribir, es ver qué tenemos, un File, qué métodos queremos, alguno que nos permita leer String y elegir la clase que nos interese.

En el caso de la lectura es un poco más complejo. No hay una clase que admita File y tenga métodos para leer String. Mirando la API, vemos que el método readLine() que nos interesa y que es capaz de leer una línea y dárnosla como String está en la clase BufferedReader. Desgraciadamente esta clase admite en su constructor un Reader y no un File que es lo que tenemos. El asunto se nos complica un poco. Debemos buscar una clase que herede de Reader y que admita un File. Buscando, buscando, encontramos que FileReader cumple con estos requisitos.

Bueno, construir el BufferedReader es algo más complejo

BufferedReader reader = new BufferedReader(new FileReader(fichero));

BufferedReader va leyendo de línea en línea. No lee los retornos de carro. Debemos hacer un bucle para ir leyendo. Puede ser similar a este

String linea = reader.readLine();
while (linea != null)
{
// Aquí lo que tengamos que hacer con la línea puede ser esto
areaTexto.append(linea);
linea = reader.readLine();
}

Si hacemos esto y miramos el resultado nos llevamos el primer chasco. Salen todas las líneas seguidas, no sale cada línea en una línea. El problema es que readLine() nos devuelve la línea, pero sin el retorno de carro al final. Si vamos añadiendo en el area de texto, debemos añadir nosotros desde nuestro código los retornos de carro.

¿Cual es el retorno de carro?. En windows el retorno de carro consiste en dos caracteres seguidos /r/n. En unix el retorno de carro sólo es uno /n. ¿Qué ponemos para que nuestro programa siga siendo portable?. La clase System de java nos permite consultar este tipo de cosas. Si ponemos

String retornoDeCarro = System.getProperty("line.separator");

en retornoCarro obtendremos el retorno de carro adecuado para nuestro sistema operativo. En System.getProperties() de la API puedes ver una lista de cosas interesantes que se pueden obtener, como el nombre del sistema operativo, el directorio actual de ejecución o el nombre del usuario.

Nuestro código quedaría así

String linea = reader.readLine();
while (linea != null)
{
// Aquí lo que tengamos que hacer con la línea puede ser esto
areaTexto.append(linea);
areaTexto.append(System.getProperty("line.separator"));
linea = reader.readLine();
}

Por supuesto, no se nos debe olvidar cerrar el fichero cuando terminemos

reader.close();

La clase StringBuffer

En el ejemplo hemos ido componiendo el texto directamente sobre el area de texto, usando su método append().

Otra opción es componer el texto directamente sobre un String y luego añadirlo todo de golpe. El código quedaría más o menos así

String lineaTotal="";
String linea = reader.readLine();
while (linea != null)
{
lineaTotal = lineaTotal + linea + System.getProperty("line.separator");
linea = reader.readLine();
}
areaTexto.setText(lineaTotal);
reader.close();

Esta opción es válida, pero no es eficiente. Se crean demasiadas clases String intermedias que se dejan luego para el recolector de basura. Para este tipo de cosas, java tiene la clase StringBuffer. Es básicamente un String, pero que permite ser modificado, añadiendo y borrando cosas de forma eficiente.

El código con esta clase quedaría así

StringBuffer lineaTotal="";
String linea = reader.readLine();
while (linea != null)
{
lineaTotal.append(linea);
lineaTotal.append(System.getProperty("line.separator"));
linea = reader.readLine();
}
areaTexto.setText(lineaTotal.toString());
reader.close();

martes, 21 de septiembre de 2010

GUI segunda parte

//***************************************************************************

package paquete1;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import paquete2.operaciones;
import javax.swing.*;

public class interfaz {


JFrame frame;
JPanel mipanel;
JLabel lblnum1,lblnum2,lblnum3,lblresultado,lblspace1,lblspace2,lblspace3,lblspace4,lblspace5,lblspace6,lblspace7,lblspace8,lblspace9,lblspace10,lblspace11,lblspace12,lblspace13,lblspace14;
JButton boton,botonr,botond,botonm;
JTextField txtnum1,txtnum2,txtnum3,txtresultado;



public static void main(String[] arg){

interfaz miformulario = new interfaz();

}

// creo el constructor de la clase......
public interfaz(){

//1.creo el frame
frame = new JFrame("Calculadora de tercer semestre");
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

// 2. creo el panel que contiene los objetos y le asigno la grilla
mipanel = new JPanel(new GridLayout(7,4));

//3. creo etiquetas o labels
lblnum1 = new JLabel("Primer Numero: ");
lblnum2 = new JLabel("Segundo Numero: ");
lblnum3 = new JLabel("Tercer Numero: ");
lblspace1 = new JLabel(" ");
lblspace2 = new JLabel(" ");
lblspace3 = new JLabel(" ");
lblspace4 = new JLabel(" ");
lblspace5 = new JLabel(" ");
lblspace6 = new JLabel(" ");
lblspace7 = new JLabel(" ");
lblspace8= new JLabel(" ");
lblspace9 = new JLabel(" ");
lblspace10 = new JLabel(" ");
lblspace11 = new JLabel(" ");
lblspace12 = new JLabel(" ");
lblspace13 = new JLabel(" ");
lblspace14 = new JLabel(" ");


lblresultado = new JLabel("El resultado es: ");

//4.creo los cuadros de texto y les doy un tamaño
txtnum1 = new JTextField(10);
txtnum2 = new JTextField(10);
txtnum3 = new JTextField(10);
txtresultado = new JTextField(10);

// 5- creo botones
boton = new JButton("Sumar");
botonr = new JButton("1");

//agrego los objetos al panel
mipanel.add(lblspace1);
mipanel.add(lblspace2);
mipanel.add(lblspace3);
mipanel.add(lblspace4);
mipanel.add(lblspace5);
mipanel.add(lblnum1);
mipanel.add(txtnum1);
mipanel.add(lblspace6);
mipanel.add(lblspace7);
mipanel.add(lblnum2);

mipanel.add(txtnum2);
mipanel.add(lblspace8);
mipanel.add(lblspace9);

mipanel.add(lblnum3);
mipanel.add(txtnum3);
mipanel.add(lblspace10);
mipanel.add(lblspace11);
mipanel.add(lblresultado);
mipanel.add(txtresultado);
mipanel.add(lblspace12);
mipanel.add(lblspace13);
mipanel.add(boton);
mipanel.add(botonr);
mipanel.add(lblspace14);

// agregamos el panel o contenedor al frame o formulario
frame.getContentPane().add(mipanel,BorderLayout.NORTH);


botonr.addActionListener(new ActionListener(){




public void actionPerformed(ActionEvent e) {
operaciones micalculadora= new operaciones();


String acum=txtresultado.getText()+"1";

// txtresultado.setText(String.valueOf(micalculadora.resta(Integer.parseInt(txtnum1.getText()), Integer.parseInt(txtnum2.getText()),Integer.parseInt(txtnum3.getText()))));

txtresultado.setText(acum);

}
});

frame.pack();
//frame.setSize(400, 200);
frame.setResizable(false);
frame.setVisible(true);

}


}
//**************************************************************************



este es el codigo para operaciones


package paquete2;

public class operaciones {

int resultado=0;

public int suma(int a,int b){

this.resultado=a + b;

return this.resultado;


}// cierre del afuncion suma


}// cierres de la clase operaciones

Capa GUI

package paquete1;

import java.awt.BorderLayout;
import java.awt.GridLayout;

import javax.swing.*;

public class interfaz {
//3.creo las instancias de los objetos....
JFrame miframe;
JPanel mipanel;
JLabel lblnum1,lblnum2;
JTextField txtnum1,txtnum2;
JButton boton;

//2. creo la funcion de inicio del programa main
public static void main(String[] arg){

interfaz miformulario = new interfaz();

}


// 1. creo un constructor que es una funcion con el nombre de la clase
public interfaz(){

//4. creo mis objetos utilizando las instancias creadas y primero creo el frame

miframe= new JFrame("Calculadora multifuncional");
miframe.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

//5. creo los paneles

mipanel = new JPanel(new GridLayout(4,2));

lblnum1 = new JLabel("Digite primer numero: ");
txtnum1=new JTextField(10);
lblnum2 = new JLabel("Digite segundo numero: ");
txtnum2=new JTextField(10);


mipanel.add(lblnum1);
mipanel.add(txtnum1);
mipanel.add(lblnum2);
mipanel.add(txtnum2);


//6. agregamos el panel al frame
miframe.getContentPane().add(mipanel,BorderLayout.NORTH);




miframe.pack();
miframe.setVisible(true);
miframe.setResizable(false);

}





}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Este es el codigo de la clase operaciones




package paquete2;

public class operaciones {

int resultado=0;


// funcion sumar
public int sumar(int a, int b){

this.resultado=a+b;

return this.resultado;
}// fin del funcion suma


}

martes, 31 de agosto de 2010

Agregue una nueva clase llamada Revista.java cuyo importe se basara en el día de la semana que se alquila.
Si es Sábado o Domingo el alquiler de las revistas será 5, en otro días será 2.

Alquiler3.java
public class Alquiler3 {
private int dias;
public Alquiler3(int dias) {
this.dias = dias;
}
public int getDias () {
return dias;
}
}
Item3.java
public class Item3 {
protected float calcularImporte(Alquiler3 contrato) {
return 0;
}
}
Pelicula3.java
public class Pelicula3 extends Item3 {
protected float calcularImporte(Alquiler3 contrato) {
int importe = 2*contrato.getDias();
return importe;
}
}
Equipo3.java
public class Equipo3 extends Item3 {
protected float calcularImporte(Alquiler3 contrato) {
int seguroEquipo = 50;
int importe = 5*contrato.getDias();
return seguroEquipo + importe;
}
}
Juego3.java
public class Juego3 extends Item3 {
String fabricante;
public Juego3(String fabricante) {
this.fabricante = fabricante;
}
public String getFabricante() {
return fabricante;
}
protected float calcularImporte(Alquiler3 contrato) {
String fabricante = this.fabricante;
int tasa = 0;
if (fabricante.equals("PlayStation")) tasa = 2;
if (fabricante.equals("Nintendo")) tasa = 1;
int importe = tasa*contrato.getDias();
return importe;
}
}
Libro3.java
public class Libro3 extends Item3 {
protected float calcularImporte(Alquiler3 contrato) {
return 0;
}
}
TestPolimorfismo.java
public class TestPolimorfismo {
public static void main (String[] args) {
Alquiler3 contrato = new Alquiler3(10);
Pelicula3 oscar = new Pelicula3();
System.out.println( oscar.calcularImporte(contrato) );
Equipo3 vhs = new Equipo3();
System.out.println( vhs.calcularImporte(contrato) );
Juego3 mu = new Juego3("Nintendo");
System.out.println( mu.calcularImporte(contrato) );
Libro3 quijote = new Libro3();
System.out.println( quijote.calcularImporte(contrato) );
}
}

lunes, 23 de agosto de 2010

Interfaces

Interfaces
Concepto de Interface

El concepto de Interface lleva un paso más adelante la idea de las clases abstractas. En Java una interface es una clase abstracta pura, es dcir una clase donde todos los métodos son abstractos (no se implementa ninguno). Permite al diseñador de clases establecer la forma de una clase (nombres de métodos, listas de argumentos y tipos de retorno, pero no bloques de código). Una interface puede también contener datos miembro, pero estos son siempre static y final. Una interface sirve para establecer un 'protocolo' entre clases.

Para crear una interface, se utiliza la palabra clave interface en lugar de class. La interface puede definirse public o sin modificador de acceso, y tiene el mismo significado que para las clases. Todos los métodos que declara una interface son siempre public.

Para indicar que una clase implementa los métodos de una interface se utiliza la palabra clave implements. El compilador se encargará de verificar que la clase efectivamente declare e implemente todos los métodos de la interface. Una clase puede implementar más de una interface.
Declaración y uso

Una interface se declara:

interface nombre_interface {
tipo_retorno nombre_metodo ( lista_argumentos ) ;
. . .
}

Por ejemplo:

interface InstrumentoMusical {
void tocar();
void afinar();
String tipoInstrumento();
}

Y una clase que implementa la interface:

class InstrumentoViento extends Object implements InstrumentoMusical {
void tocar() { . . . };
void afinar() { . . .};
String tipoInstrumento() {}
}

class Guitarra extends InstrumentoViento {
String tipoInstrumento() {
return "Guitarra";
}
}

La clase InstrumentoViento implementa la interface, declarando los métodos y escribiendo el código correspondiente. Una clase derivada puede también redefinir si es necesario alguno de los métodos de la interface.
Referencias a Interfaces

Es posible crear referencias a interfaces, pero las interfaces no pueden ser instanciadas. Una referencia a una interface puede ser asignada a cualquier objeto que implemente la interface. Por ejemplo:

InstrumentoMusical instrumento = new Guitarra();
instrumento.play();
System.out.prinln(instrumento.tipoInstrumento());

InstrumentoMusical i2 = new InstrumentoMusical(); //error.No se puede instanciar

Extensión de interfaces

Las interfaces pueden extender otras interfaces y, a diferencia de las clases, una interface puede extender más de una interface. La sintaxis es:

interface nombre_interface extends nombre_interface , . . . {
tipo_retorno nombre_metodo ( lista_argumentos ) ;
. . .
}

Agrupaciones de constantes

Dado que, por definición, todos los datos miembros que se definen en una interface son static y final, y dado que las interfaces no pueden instanciarse resultan una buena herramienta para implantar grupos de constantes. Por ejemplo:

public interface Meses {
int ENERO = 1 , FEBRERO = 2 . . . ;
String [] NOMBRES_MESES = { " " , "Enero" , "Febrero" , . . . };
}

Esto puede usarse simplemente:

System.out.println(Meses.NOMBRES_MESES[ENERO]);


Un ejemplo casi real

El ejemplo mostrado a continuación es una simplificación de como funciona realmente la gestión de eventos en el sistema gráfico de usuario soportado por el API de Java (AWT o swing). Se han cambiado los nombres y se ha simplificado para mostrar un caso real en que el uso de interfaces resuelve un problema concreto.

Supongamos que tenemos una clase que representa un botón de acción en un entorno gráfico de usuario (el típico botón de confirmación de una acción o de cancelación). Esta clase pertenecerá a una amplia jerarquía de clases y tendrá mecanismos complejos de definición y uso que no son objeto del ejemplo. Sin embargo podríamos pensar que la clase Boton tiene miembros como los siguientes.

class Boton extends . . . {
protected int x , y, ancho, alto; // posicion del boton
protected String texto; // texto del boton
Boton(. . .) {
. . .
}
void dibujar() { . . .}
public void asignarTexto(String t) { . . .}
public String obtenerTexto() { . . .)
. . .
}

Lo que aquí nos interesa es ver lo que sucede cuando el usuario, utilizando el ratón pulsa sobre el botón. Supongamos que la clase Boton tiene un método, de nombre por ejemplo click(), que es invocado por el gestor de ventanas cuando ha detectado que el usuario ha pulsado el botón del ratón sobre él. El botón deberá realizar alguna acción como dibujarse en posición 'pulsado' (si tiene efectos de tres dimensiones) y además, probablemente, querrá informar a alguien de que se ha producido la acción del usuario. Es en este mecanismo de 'notificación' donde entra el concepto de interface. Para ello definimos una interface Oyente de la siguiente forma:

interface Oyente {
void botonPulsado(Boton b);
}

La interface define un único método botonPulsado. La idea es que este método sea invocado por la clase Boton cuando el usuario pulse el botón. Para que esto sea posible en algún momento hay que notificar al Boton quien es el Oyente que debe ser notificado. La clase Boton quedaría:

class Boton extends . . . {
. . .
private Oyente oyente;
void registrarOyente(Oyente o) {
oyente = o;
}
void click() {
. . .
oyente.botonPulsado(this);
}
}

El método registrarOyente sirve para que alguien pueda 'apuntarse' como receptor de las acciones del usuario. Obsérvese que existe una referencia de tipo Oyente. A Boton no le importa que clase va a recibir su notificación. Simplemente le importa que implante la interface Oyente para poder invocar el método botonPulsado. En el método click se invoca este método. En el ejemplo se le pasa como parámetro una referencia al propio objeto Boton. En la realidad lo que se pasa es un objeto 'Evento' con información detallada de lo que ha ocurrido.

Con todo esto la clase que utiliza este mecanismo podría tener el siguiente aspecto:

class miAplicacion extends . . . implements Oyente {
public static main(String [] args) {
new miAplicacion(. . .);
. . .
}
. . .
miAplicacion(. . .) {
. . .
Boton b = new Boton(. . .);
b.registrarOyente(this);
}

. . .
void botonPulsado(Boton x) {
// procesar click
. . .
}
}

Obsérvese en el método registrarOyente que se pasa la referencia thisque en el lado de la clase Boton es recogido como una referencia a la interface Oyente. Esto es posible porque la clase miAplicacion implementa la interface Oyente . En términos clásicos de herencia miAplicacion ES un Oyente .

martes, 17 de agosto de 2010

Polimorfismo en Java

Hola muchachos!!!


Antes de iniciar con el tema de polimorfismo....recordemos algunos conceptos

Declaración de la clase

La clase se declara mediante la línea public class Contador. En el caso más general, la declaración de una clase puede contener los siguientes elementos:

[public] [final | abstract] class Clase [extends ClaseMadre] [implements Interfase1 [, Interfase2 ]…]

o bien, para interfaces:

[public] interface Interfase [extends InterfaseMadre1 [, InterfaseMadre2 ]…]

Como se ve, lo único obligatorio es class y el nombre de la clase. Las interfases son un caso de clase particular que veremos más adelante.
Public, final o abstract

Definir una clase como pública (public) significa que puede ser usada por cualquier clase en cualquier paquete. Si no lo es, solamente puede ser utilizada por clases del mismo paquete (más sobre paquetes luego; básicamente, se trata de un grupo de clases e interfaces relacionadas, como los paquetes de biblioteca incluídos con Java).

Una clase final (final) es aquella que no puede tener clases que la hereden. Esto se utiliza básicamente por razones de seguridad (para que una clase no pueda ser reemplazada por otra que la herede), o por diseño de la aplicación.

Una clase abstracta (abstract) es una clase que puede tener herederas, pero no puede ser instanciada. Es, literalmente, abstracta (como la clase Number definida en java.lang). ¿Para qué sirve? Para modelar conceptos. Por ejemplo, la clase Number es una clase abstracta que representa cualquier tipo de números (y sus métodos no están implementados: son abstractos); las clases descendientes de ésta, como Integer o Float, sí implementan los métodos de la madre Number, y se pueden instanciar.

Por lo dicho, una clase no puede ser final y abstract a la vez (ya que la clase abstract requiere descendientes…)

¿Un poco complejo? Se va a entender mejor cuando veamos casos particulares, como las interfases (que por definición son abstractas ya que no implementan sus métodos).
Extends

La instrucción extends indica de qué clase desciende la nuestra. Si se omite, Java asume que desciende de la superclase Object.

Cuando una clase desciende de otra, esto significa que hereda sus atributos y sus métodos (es decir que, a menos que los redefinamos, sus métodos son los mismos que los de la clase madre y pueden utilizarse en forma transparente, a menos que sean privados en la clase madre o, para subclases de otros paquetes, protegidos o propios del paquete). Veremos la calificación de métodos muy pronto, a no desesperar!
Implements

Una interfase (interface) es una clase que declara sus métodos pero no los implementa; cuando una clase implementa (implements) una o más interfases, debe contener la implementación de todos los métodos (con las mismas listas de parámetros) de dichas interfases.

Esto sirve para dar un ascendiente común a varias clases, obligándolas a implementar los mismos métodos y, por lo tanto, a comportarse de forma similar en cuanto a su interfase con otras clases y subclases.
Interface

Una interfase (interface), como se dijo, es una clase que no implementa sus métodos sino que deja a cargo la implementación a otras clases. Las interfases pueden, asimismo, descender de otras interfases pero no de otras clases.

Todos sus métodos son por definición abstractos y sus atributos son finales (aunque esto no se indica en el cuerpo de la interfase).

Son útiles para generar relaciones entre clases que de otro modo no están relacionadas (haciendo que implementen los mismos métodos), o para distribuir paquetes de clases indicando la estructura de la interfase pero no las clases individuales (objetos anónimos).

Si bien diferentes clases pueden implementar las mismas interfases, y a la vez descender de otras clases, esto no es en realidad herencia múltiple ya que una clase no puede heredar atributos ni métodos de una interface; y las clases que implementan una interfase pueden no estar ni siquiera relacionadas entre sí.


El polimorfismo es un concepto de la programación orientada a objetos que nos permite programar en forma general, en lugar de hacerlo en forma específica. En general nos sirve para programar objetos con características comunes y que todos estos compartan la misma superclase en una jerarquía de clases, como si todas fueran objetos de la superclase. Esto nos simplifica la programación.

Recuerde el ejemplo del ecosistema, en donde todos los objetos de las distintas especies heredaban de una superclase llamada Animal, que brindaba la información general de cualquier animal, independiente de su especie. Sin embargo, cada especie hace un uso particular de cada uno de los métodos u operaciones de la clase Animal. El método comer() no se ejecutará de la misma manera en un León() o en un Pavo(). Lo mismo ocurre para métodos moverse() en objetos de tipo Tiburón() o Gallina(), aunque todas las especies realicen estos métodos. A la sobrescritura o implementación específica de métodos es la clave del polimorfismo.

Para poner en práctica se hará un ejemplo bastante sencillo. Se hará una librería de clases que represente figuras tridimensionales y bidimensionales, y su respectiva jerarquía de clases. Las clases deben ser capaces de tener funcionamiento bastante básico, como obtener áreas, volúmenes y perímetros de la figura correspondiente.


La representación de la jerarquía sería como ésta:


Click a la imagen para verla más grande...


La superclase de dicha jerarquía podría ser muy parecida a ésta:

public abstract class figura {

protected String nombre;
protected int color;
protected int grosorBorde;

public String getNombre(){
return this.nombre;
}
public void setNombre(String n){
this.nombre=n;
}

public int getColor(){
return this.color;
}

public void setColor(int c){
this.color=c;
}

public int getGrosorBorde(){
return this.grosorBorde;
}

public void setGrosorBorde(int g){
this.grosorBorde=g;
}

public abstract void dibujar();
}

Las siguientes clases en el nivel de la jerarquía podrían quedar muy parecidas a éstas:

public abstract class figura2D extends figura {

public abstract int calcularArea();

public abstract int calcularPerimetro();
}

public abstract class figura3D extends figura {

public abstract int calcularVolumen();
}

Se le pide que forme las clases de la parte inferior de la jerarquía y que representarían los objetos a instanciarse.

Además, debe de realizar una implementación de esta librería, en donde el usuario pueda crear nuevas figuras y que éstas se almacenen en un arreglo de figuras.


Ejercicios:


* Realice una jerarquía de clases en donde se representen un cuadrilátero.


* Mediante esa superclase, realice las clases rectángulo, cuadrado, paralelogramo y trapezoide; que heredarán de ella, convirtiéndose prácticamente en objetos cuadrilátero (superclase).

martes, 10 de agosto de 2010

Taller HERENCIA -10 -08-2010

Ejercicio de diagnostico...POO

1.)Crea una clase CRectángulo. La clase tiene dos datos miembro, largo y ancho. La clase cuenta con
métodos que calculan el perímetro (obtenPerímetro) y el área (obtenÁrea) del rectángulo, así como
métodos para obtener y poner los valores correspondientes a los atributos largo y ancho. Los métodos
poner deben comprobar que tanto largo como ancho sean mayores que 0 y menores que 20.



Probar y analizar

2.)Construir una clase final Math2 que amplíe las declaraciones de métodos estáticos de la clase
Math y que incluya funciones que devuelvan, respectivamente, el máximo, el mínimo, el
sumatorio, la media aritmética y la media geométrica de un array de números reales dado como
parámetro.



Solucion....

public final class Math2 {
public static double min (double [] v) {
double menor = v[0];
for (int i=0; i<"v.length"; i++) {
if (menor>v[i]) { menor=v[i]; }
}
return menor;
}
public static double max (double [] v) {

double mayor = v[0];
for (int i=0; i<"v.length"; i++) {
if (mayor}
return mayor;
}
public static double sum (double [] v) {
double sumatorio =0.0;
for (int i=0; i<"v.length"; i++) {
sumatorio=sumatorio+v[i];
}
return sumatorio;
}
public static double mediaAritmetica (double [] v) {
double sumatorio =0.0;
for (int i=0; i<"v.length"; i++) {
sumatorio+=v[i];
}
return (sumatorio/"v.length");
}
public static double mediaGeometrica (double [] v) {
double producto =1.0;
for (int i=0; i<"v.length"; i++) {
producto*=v[i];
}
return Math.sqrt(producto);
}
}
Ejemplo de uso de la clase Math2:
/**
* Programa PruebaMath2
* A. Garcia-Beltran - diciembre, 2004
*/
public class PruebaMath2 {
public static void main (String [] args) {
double [] x = new double[10];
for (int i=0; i<"x.length"; i++) {
x[i] = 5*Math.random();
System.out.println("x["+i+"] = "+x[i]);
}
System.out.println("Minimo : " + Math2.min(x));
System.out.println("Maximo : " + Math2.max(x));
System.out.println("Sumatorio : " + Math2.sum(x));
System.out.println("Media arit. : " + Math2.mediaAritmetica(x));
System.out.println("Media geom. : " + Math2.mediaGeometrica(x));
}
}


Salida por pantalla de la ejecución del código anterior:
$>java PruebaMath2
x[0] = 3.9295964172220037
x[1] = 3.3033982387050598
x[2] = 0.38413320538334517
x[3] = 1.441533972096129
x[4] = 0.5194720253569335
x[5] = 0.5801662478628711
x[6] = 4.370186448410964
x[7] = 1.2908820504663692
x[8] = 3.8520244358555944
x[9] = 0.1450533020411976
Minimo : 0.1450533020411976
Maximo : 4.370186448410964
Sumatorio : 19.816446343400468
Media arit. : 1.981644634340047
Media geom. : 2.6131642597311173

3.)Diseñe una clase cualquiera donde se muestre un ejemplo de sobrecarga de metodos...