Professional Documents
Culture Documents
Text;
class Fraccion { public Fraccion() { this.num = 0; this.den = 0; } public Fraccion(int num, int den) { this.num = num; this.den = den; }
//Mtodos public Fraccion multiplica (Fraccion F1, Fraccion F2) { int sol_num = F1.num * F2.num; int sol_den = F1.den * F2.den; Fraccion soluc = new Fraccion(sol_num, sol_den); return soluc; } } class FraccionApp { static void Main(string[] args) { Fraccion uno = new Fraccion(1, 2); Fraccion dos = new Fraccion(3, 5); Fraccion solucion = new Fraccion();
En esta pgina vamos a definr una clase denominada Fraccion con dos miembros dato: el numerador y el denominador, y varias funciones miembro que realizan las operaciones entre fracciones. El lenguaje Java no tiene la caracterstica de la sobrecarga de operadores como el lenguaje C++. En este lenguaje es posible sobrecargar los operadores aritmticos, como funciones miembro o como funciones amigas (friend) para que se realicen las operaciones entre entidades definidas por el usuario tal como las pensamos o las escribimos en un papel. Por ejemplo, si a y b son dos fracciones (objetos de la clase Fraccion) podemos escribir c=a+b; para obtener la fraccin c resultado de la suma de a y b. Definiremos las operaciones en Java de un modo similar al lenguaje C, pero como en Java no existen funciones que no sean miembros de una clase, definiremos las operaciones como funciones estticas de una clase que denominamos Fraccion. fraccion1: Fraccion.java, FraccionApp1.java
Los constructores
Definiremos dos constructores, el constructor por defecto, que da al numerdor el valor cero, y al denominador el valor uno, y el constructor explcito.
public Fraccion() { num=0; den=1; } public Fraccion(int x, int y) { num=x; den=y; }
Para codificar la funcin plantearemos el procedimiento de sumar dos fracciones a y b, cuyos numeradores son a.num y b.num, y cuyos denominadores son a.den y b.den, respectivamente. El resultado se guarda en la fraccin c. El numerador c.num y el denominador c.den se obtienen del siguiente modo:
La suma de dos fracciones es otra fraccin c que tiene por numerador c.num.
c.num=a.num*b.den+b.num*a.den;
Fraccion multiplicar(Fraccion a, Fraccion b){ Fraccion c=new Fraccion(); c.num=a.num*b.num; c.den=a.den*b.den; return c; }
La funcin inversa, recibe una fraccin en su nico argumento y devuelve una fraccin cuyo numerador es el denominador de la fraccin argumento, y cuyo denominador es el numerador de dicha fraccin.
La operacin divisin de dos fracciones es equivalente a multiplicar la fraccin a por la inversa de b, de este modo aprovechamos el cdigo de la funcin inversa.
Fraccion dividir(Fraccion a, Fraccion b){ return multiplicar(a, inversa(b)); }
En la primera iteracin, se halla el resto r de dividir el primero u entre el segundo v. Se asigna a u el divisor v, y se asigna a v el resto r. En la segunda iteraccin, se halla el resto r de dividir u entre v. Se asigna a u el divisor v, y se asigna a v el resto r. Se repite el proceso hasta que el resto r sea cero. El mximo comn divisor ser el ltimo valor de v.
1260=231*5+105 231=105*2+21 105=21*5+0 el mximo comn divisor es 21. Definimos en la clase Fraccion una funcin mcd que calcula y devuelve el mximo comn divisor del numerador y del denominador.
int mcd(){ int u=Math.abs(num); int v=Math.abs(den); if(v==0){ return u; } int r; while(v!=0){ r=u%v; u=v; v=r; } return u; }
A continuacin definimos la funcin simplificar, de modo que al aplicarlo sobre una fraccin, dicha fraccin se reduzca a la fraccin equivalente ms simple. Para ello, se divide numerador y denominador por el mximo comn divisor de ambos nmeros, y devuelve la fraccin simplificada.
Fraccion simplificar(){ int dividir=mcd(); num/=dividir; den/=dividir; return this; }
Aqu tenemos otro ejemplo del uso de la palabra reservada this. Los miembros dato cambian al dividirlos entre el mximo comn divisor y la funcin devuelve el objeto actual, this.
Un objeto de la clase Fraccion llama a la funcin miembro imprimir para mostrar en la consola (una ventana DOS) los valores que guardan sus miembros dato, num y den, el numerador y el denominador. La funcin imprimir as definida no nos servir cuando la clase Fraccion se emplee en un contexto grfico. Ahora bien, como vamos a ver a continuacin el lenguaje Java nos proporciona una solucin a este problema. Aunque no se define explcitamente, la clase Fraccion deriva de la clase base Object (la estudiaremos en el siguiente captulo) y redefine la funcin miembro pblica toString, cuya tarea es la de dar una representacin en forma de texto de la fraccin.
public String toString(){ String texto=num+" / "+den; return texto; }
En la definicin de toString vemos que el operador + se usa para concatenar strings (el lenguaje Java convierte automticamente un dato primitivo en su representacin textual cuando se concatena con un string). Para mostar en la consola el numerador y el denominador de una fraccin (objeto de la clase Fraccion) a basta escribir
System.out.println(a);
donde 20, 30 son las coordenadoas de la lnea base del primer carcter. Esta sentencia equivale a la llamada explcita
g.drawString("fraccin: "+a.toString(), 20, 30);
La redefinicin de la funcin toString devuelve un string un objeto de la clase String que guarda la representacin en forma de texto de los objetos de una determinada clase. De este modo, una clase que redefina toString puede emplearse en cualquier mbito.
La clase Fraccion
Ahora ponemos las funciones miembro dentro de la clase Fraccion, anteponiendo en las funciones que representan operaciones la palabra reservada static.
public class Fraccion { private int num; private int den; public Fraccion() { num=0; den=1; } public Fraccion(int x, int y) { num=x; den=y; } public static Fraccion sumar(Fraccion a, Fraccion b){ Fraccion c=new Fraccion(); c.num=a.num*b.den+b.num*a.den; c.den=a.den*b.den; return c; } public static Fraccion restar(Fraccion a, Fraccion b){ Fraccion c=new Fraccion(); c.num=a.num*b.den-b.num*a.den; c.den=a.den*b.den; return c; } public static Fraccion multiplicar(Fraccion a, Fraccion b){ return new Fraccion(a.num*b.num, a.den*b.den); } public static Fraccion inversa(Fraccion a){ return new Fraccion(a.den, a.num); } public static Fraccion dividir(Fraccion a, Fraccion b){ return multiplicar(a, inversa(b)); } private int mcd(){ int u=Math.abs(num); int v=Math.abs(den); if(v==0){ return u; } int r; while(v!=0){ r=u%v; u=v; v=r; } return u; } public Fraccion simplificar(){ int dividir=mcd(); num/=dividir; den/=dividir; return this; } public String toString(){
Cuando se pone una fraccin x como argumento de la funcin println o se concatena con un string se llama automticamente a la funcin miembro toString, lo que equivale a la siguiente llamada
System.out.println("x--> "+x.toString());
Operaciones combinadas
System.out.println(resultado.simplificar());
Modificadores de acceso
Este ejemplo ilustra una faceta importante de los lenguajes de Programacin Orientada a Objetos denominada encapsulacin. El acceso a los miembros de una clase est controlado. Para usar una clase, solamente necesitamos saber que funciones miembro se pueden llamar y a qu datos podemos acceder, no necesitamos saber como est hecha la clase, como son sus detalles internos. Una vez que la clase est depurada y probada, la clase es como una caja negra. Los objetos de dicha clase guardan unos datos, y estn caracterizados por una determinada conducta. Este ocultamiento de la informacin niega a la entidades exteriores el acceso a los miembros privados de un objeto. De este modo, las entidades exteriores acceden a los datos de una manera controlada a travs de algunas funciones miembro. Para acceder a un miembro pblico (dato o funcin) basta escribir.
objeto_de_la_clase_Fraccion.miembro_pblico_no_esttico clase_Fraccion.miembro_pblico_esttico
Delante de los miembros dato, como podemos ver en el listado hemos puesto las plabras reservadas public y private.
Miembros pblicos
Los miembros pblicos son aquellos que tienen delante la palabra public, y se puede acceder a ellos sin ninguna restriccin.
Miembros privados
Los miembros privados son aquellos que tienen delante la palabra private, y se puede acceder a ellos solamente dentro del mbito de la clase. Los miembros dato num y den son privados, y tambin la funcin que calcula el mximo comn divisor mcd, que es una funcin auxiliar de la funcin miembro publica simplificar. El usuario solamente precisa saber que dispone de una funcin pblica que le permite simplificar una fraccin, pero no necesita saber cul es el procedimiento empleado para simplificar fracciones. As declaramos la funcin mcd como privada y simplificar como pblica.
Cuando no se pone ningn modificador de acceso delante de los miembros, se dice que son accesibles dentro del mismo paquete (package). Esto es lo que hemos hecho en los ejemplos estudiados hasta esta seccin.
package es la primera sentencia que se pone en un archivo .java. El nombre del paquete es el mismo que el nombre del subdirectorio que contiene los archivos .java. Cada archivo .java contiene habitualmente una clase. Si tiene ms de una solamente una de ellas es pblica. El nombre de dicha clase coincide con el nombre del archivo. Como el lector se habr dado cuenta hay una correspondencia entre archivos y clases, entre paquetes y subdirectorios. El Entorno Integrado de Desarrollo (IDE) en el que creamos los programas facilita esta tarea sin que el usuario se aperciba de ello.
Podemos llamar una sla vez a la funcin miembro ordenar en el constructor, despus de haber creado el array, y evitar as la reiteracin de llamadas a dicha funcin en valorMayor, valorMenor e imprimir.
public Lista(int[] x) { this.x=x; n=x.length; ordenar(); } public int valorMayor(){ return x[n-1]; } public int valorMenor(){ return x[0]; }
La funcin miembro ordenar, es una funcin auxiliar de las otras funciones miembro pblicas, por tanto, podemos ponerle delante el modificador de acceso private. El usuario solamente est interesado en el valor medio, el valor mayor y menor de un conjunto de
datos, pero no est interesado en el procedimiento que permite ordenar el conjunto de datos. Como ocurre en la vida moderna usamos muchos aparatos pero no tenemos por que conocer sus detalles internos y cmo funcionan por dentro. Una clase es como uno de estos aparatos modernos, el usuario solamente tiene que conocer qu hace la clase, a qu miembros tiene acceso, pero no como est implementada en software.
Sustitumos la funcin miembro imprimir por la redefinicin de toString. Para redefinir una funcin, tiene que tener el mismo nombre, los mismos modificadores, el mismo tipo de retorno y los mismos parmetros y del mismo tipo en la clase base y en la clase derivada. Para evitar errores, el mejor procedimiento es el de ir al cdigo de la clase base Object, copiar la lnea de la declaracin de toString, pegarla en la definicin de nuestra clase, y a continuacin definir dicha funcin.
public class Lista { private int[] x; //array de datos private int n; //dimensin //... public String toString(){ String texto=""; for(int i=0; i<n; i++){ texto+="\t"+x[i]; } return texto; }
La llamada a la funcin toString se realiza implcitamente en el argumento de la funcin System.out.println, o bien, al concatenar un string y un objeto de la clase Lista.
Lista lista=new Lista(new int[]{60, -4, 23, 12, -16}); System.out.println("Mostrar la lista"); System.out.println(lista); public class Lista { private int[] x; //array de datos private int n; //dimensin public Lista(int[] x) { this.x=x; n=x.length; ordenar(); } public double valorMedio(){ int suma=0; for(int i=0; i<n; i++){ suma+=x[i]; } return (double)suma/n; } public int valorMayor(){ return x[n-1]; } public int valorMenor(){ return x[0]; } private void ordenar(){ int aux; for(int i=0; i<n-1; i++){ for(int j=i+1; j<n; j++){ if(x[i]>x[j]){ aux=x[j]; x[j]=x[i]; x[i]=aux; } } } } public String toString(){ String texto=""; for(int i=0; i<n; i++){ texto+="\t"+x[i]; } return texto; } }