?? java6.htm
字號:
<HTML>
<HEAD>
<TITLE>Java desde Cero</TITLE>
</HEAD>
<BODY background=/iconos/1.gif TEXT=000000 LINK=FF0000 VLINK=A62A2A>
<H1>Hagamos algo...</H1>
<P>
Bueno, vamos a hacer una pequeña aplicación para
practicar un poco.
<P>
Para empezar, vamos a desarrollar un poquito una clase para trabajar
con números complejos.
<H2>La clase Complejo</H2>
<PRE>
<FONT SIZE=2>// grabar como Complejo.java
// compilar con "javac Complejo.java"
public final class Complejo extends Number {
// atributos:
private float x;
private float y;
// constructores:
public Complejo() {
x = 0;
y = 0;
}
public Complejo(float rx, float iy) {
x = rx;
y = iy;
}
// métodos:
// Norma
public final float Norma() {
return (float)Math.sqrt(x*x+y*y);
}
public final float Norma(Complejo c) {
return (float)Math.sqrt(c.x*c.x+c.y*c.y);
}
// Conjugado
public final Complejo Conjugado() {
Complejo r = new Complejo(x,-y);
return r;
}
public final Complejo Conjugado(Complejo c) {
Complejo r = new Complejo(c.x,-c.y);
return r;
}
// obligatorios (son abstractos en Number):
public final double doubleValue() {
return (double)Norma();
}
public final float floatValue() {
return Norma();
}
public final int intValue() {
return (int)Norma();
}
public final long longValue() {
return (long)Norma();
}
public final String toString() {
if (y<0)
return x+"-i"+(-y);
else
return x+"+i"+y;
}
// Operaciones matemáticas
public static final Complejo Suma(Complejo c1, Complejo c2) {
return new Complejo(c1.x+c2.x,c1.y+c2.y);
}
public static final Complejo Resta(Complejo c1, Complejo c2) {
return new Complejo(c1.x-c2.x,c1.y-c2.y);
}
public static final Complejo Producto(Complejo c1, Complejo c2) {
return new Complejo(c1.x*c2.x-c1.y*c2.y,c1.x*c2.y+c1.y*c2.x);
}
// Nos va a venir bien para aprender excepciones...
// como división por cero!
public static final Complejo DivEscalar(Complejo c, float f) {
return new Complejo(c.x/f,c.y/f);
}
public static final Complejo Cociente(Complejo c1, Complejo c2) {
float x = c1.x*c2.x+c1.y*c2.y;
float y = -c1.x*c2.y+c1.y*c2.x;
float n = c2.x*c2.x+c2.y*c2.y;
Complejo r = new Complejo(x,y);
return DivEscalar(r,n);
}
}<BR>
</FONT>
</PRE>
<P>
Podemos hacer algunos comentarios...
<P>
Primero: no hay include aquí, ya que la única biblioteca
que usamos es <B>java.lang</B> y se incluye automáticamente.
<P>
Segundo: la clase es <FONT FACE="Arial">public final</FONT>, lo
que implica que cualquier clase en éste u otros paquetes
puede utilizarla, pero ninguna clase puede heredarla (o sea que
es una clase estéril...).
<P>
Hagamos un resumen de los atributos y métodos de la clase:
<PRE>
<FONT SIZE=2> // atributos:
private float x;
private float y;</FONT>
</PRE>
<P>
Siendo privados, no podemos acceder a ellos desde el exterior.
Como además la clase es final, no hay forma de acceder
a <FONT FACE="Arial">x</FONT> e <FONT FACE="Arial">y</FONT>. Además,
al no ser static, cada instancia de la clase tendrá su
propio <FONT FACE="Arial">x</FONT> e <FONT FACE="Arial">y</FONT>.
<PRE>
<FONT SIZE=2> // constructores:
public Complejo()
public Complejo(float rx, float iy)</FONT>
</PRE>
<P>
La clase tiene dos constructores, que se diferencian por su "firma"
(<I>signature</I>), o sea por la cantidad y tipo de parámetros.
El primero nos sirve para crear un objeto de tipo <B>Complejo</B>
y valor indefinido (aunque en realidad el método lo inicializa
en cero); con el segundo, podemos definir el valor al crearlo.
<PRE>
<FONT SIZE=2> // métodos:
public final float Norma()
public final float Norma(Complejo c)
public final Complejo Conjugado()
public final Complejo Conjugado(Complejo c)</FONT>
</PRE>
<P>
Estos métodos también son duales; cuando los usamos
sin parámetros devuelven la norma o el conjugado del objeto
individual (instancia):
<PRE>
<FONT SIZE=2>v = miComplejo.Norma(); // por ejemplo
otroComplejo = miComplejo.Conjugado();</FONT>
</PRE>
<P>
Con parámetros, en cambio, devuelven la norma o el conjugado
del parámetro:
<PRE>
<FONT SIZE=2> v = unComplejo.Norma(miComplejo);
otroComplejo = unComplejo.Conjugado(miComplejo);</FONT>
</PRE>
<P>
Notar que lo siguiente es inválido:
<P>
<FONT FACE="Arial"> otroComplejo = Complejo.Norma(miComplejo);
// NO SE PUEDE!</FONT>
<P>
...porque el método no es <I>static</I>, por lo tanto <B>debe</B>
llamarse para una instancia en particular (en este caso, <I>unComplejo</I>).
<BR>
<PRE>
<FONT SIZE=2> // obligatorios (son abstractos en Number):
public final double doubleValue()
public final float floatValue()
public final int intValue()
public final long longValue()</FONT>
</PRE>
<P>
Estos métodos es obligatorio definirlos, ya que en la clase
madre <I>Number</I> son métodos abstractos, o sea que debemos
implementarlos aquí.
<P>
Como todos los métodos de esta clase son final, o sea que
no puede ser redefinido. No es importante en realidad puesto que
la clase no puede tener descendientes...
<PRE>
<FONT SIZE=2> public final String toString()</FONT>
</PRE>
<P>
Este método nos sirve para representar el complejo como
una cadena de caracteres, de la forma <FONT FACE="Arial">x+iy</FONT>.
<PRE>
<FONT SIZE=2> // Operaciones matemáticas
public static final Complejo Suma(Complejo c1, Complejo c2)
public static final Complejo Resta(Complejo c1, Complejo c2)
public static final Complejo Producto(Complejo c1, Complejo c2)
public static final Complejo DivEscalar(Complejo c, float f)
public static final Complejo Cociente(Complejo c1, Complejo c2)</FONT>
</PRE>
<P>
Aquí definimos varias operaciones matemáticas. Notar
que se han definido como <FONT FACE="Arial">static</FONT>, o sea
que los métodos son únicos independientemente de
las instancias. Esto permite que los podamos ejecutar sobre una
instancia o directamente sobre la clase:
<PRE>
<FONT SIZE=2>miComplejo = unComplejo.Suma(comp1,comp2); // vale
miComplejo = Complejo.Suma(comp1,comp2); // TAMBIEN VALE!</FONT>
</PRE>
<P>
Por ejemplo, la siguiente aplicación nos muestra cómo
podemos usar algunos de estos métodos:
<PRE>
<FONT SIZE=2>// Archivo: Ejemplo5.java
// Compilar con: javac Ejemplo5.java
// Ejecutar con: java Ejemplo5
import java.io.*;
public class Ejemplo5 {
public static void main(String args[]) {
Complejo c1 = new Complejo(4,-3);
System.out.println(c1+"\tNorma="+c1.Norma());
Complejo c2 = new Complejo(-2,5);
System.out.println(c2+"\tNorma="+c2.Norma()+"\n");
System.out.println("("+c1+")/4 :"+Complejo.DivEscalar(c1,4));
System.out.println("Suma : "+Complejo.Suma(c1,c2));
System.out.println("Resta : "+Complejo.Resta(c1,c2).toString());
System.out.println("Multip: "+Complejo.Producto(c1,c2).toString());
System.out.println("Divis : "+Complejo.Cociente(c1,c2).toString());
}
}</FONT>
</PRE>
<P>
Hay varias cosas para notar: por ejemplo, que podemos declarar
las variables a la vez que las creamos:
<PRE>
<FONT SIZE=2>Complejo c1 = new Complejo(4,-3);</FONT>
</PRE>
<P>
<FONT FACE="Arial">c1</FONT> y <FONT FACE="Arial">c2</FONT> son
dos objetos (instancias) de la clase Complejo.
<P>
Notar también que no hace falta poner para imprimir:
<PRE>
<FONT SIZE=2>System.out.println(c1.toString().......);</FONT>
</PRE>
<P>
ya que <FONT FACE="Arial">println</FONT> automáticamente
usa el método<FONT FACE="Arial"> toString()</FONT> de la
clase para imprimir. Basta con poner <FONT FACE="Arial">c1</FONT>,
como en el programa, aunque <FONT FACE="Arial">c1.toString()</FONT>
también es válido.
<P>
También se ve el uso de los métodos <FONT FACE="Arial">static</FONT>,
accediéndolos directamente por la clase, en:
<PRE>
<FONT SIZE=2>System.out.println("Suma : "+Complejo.Suma(c1,c2));</FONT>
</PRE>
<P>
Y tampoco aquí usamos <FONT FACE="Arial">toString()</FONT>,
aunque no está mal si se usa <FONT FACE="Arial">Complejo.Suma(c1,c2).toString()</FONT>.
<H2>Algo sobre los métodos</H2>
<P>
Analicemos un poco ahora cómo implementamos los métodos
de la clase <I>Complejo</I>.
<PRE>
<FONT SIZE=2> public final int intValue() {
return (int)Norma();
}</FONT>
</PRE>
<P>
Ya que no podemos convertir así nomás un complejo
en un entero, para implementar estos métodos hemos elegido
usar como valor de retorno la norma del complejo. En este caso,
y dado que el método <FONT FACE="Arial">Norma()</FONT>
devuelve un <FONT FACE="Arial">float</FONT>, usamos <I>typecasting</I>,
es decir, lo convertimos en entero precediéndolo con <FONT FACE="Arial">(int)</FONT>.
<PRE>
<FONT SIZE=2> public final String toString() {
if (y<0)
return x+"-i"+(-y);
else
return x+"+i"+y;
}</FONT>
</PRE>
<P>
Aquí representamos el complejo en forma de cadena de caracteres.
Hemos usado el <I>if</I> para representar adecuadamente el signo
de la parte imaginaria. Noten también la asombrosa ayuda
que nos brinda Java, al convertir automáticamente las variables
<FONT FACE="Arial">x</FONT> e <FONT FACE="Arial">y</FONT> a String
para la concatenación (mediante el signo "+")!
<PRE>
<FONT SIZE=2> public static final Complejo Cociente(Complejo c1, Complejo c2) {
float x = c1.x*c2.x+c1.y*c2.y;
float y = -c1.x*c2.y+c1.y*c2.x;
float n = c2.x*c2.x+c2.y*c2.y;
Complejo r = new Complejo(x,y);
return DivEscalar(r,n);
}</FONT>
</PRE>
<P>
Aquí tengan en cuenta que las variables <FONT FACE="Arial">x</FONT>
e <FONT FACE="Arial">y</FONT>, definidas como <I>float</I>, no
tienen nada que ver con las variables (atributos) de la clase
que están definidas al principio de la misma, sino que
son variables locales al método.
<P>
Podemos usar <FONT FACE="Arial">return DivEscalar(r,n)</FONT>,
ya que <FONT FACE="Arial">DivEscalar</FONT> es un método
propio de la clase; no hace falta poner <FONT FACE="Arial">Complejo.DivEscalar</FONT>.
<P>
Qué pasa con <FONT FACE="Arial">r</FONT>, el new <FONT FACE="Arial">Complejo(x,y)</FONT>
que creamos? Nada; cuando un objeto no se usa más, el "recogedor
de basura" de Java lo elimina automáticamente (tarde
o temprano) de la memoria.
<PRE>
<FONT SIZE=2> public final float Norma(Complejo c) {
return (float)Math.sqrt(c.x*c.x+c.y*c.y);
}</FONT>
</PRE>
<P>
Aquí estamos usando otra clase, <B>Math</B>, que nos permite
realizar varias operaciones matemáticas. Esta clase dispone
de las constantes <FONT FACE="Arial">E</FONT> y <FONT FACE="Arial">PI</FONT>,
y los métodos:
<PRE>
<FONT SIZE=2>abs(x) valor absoluto
acos(x) arco coseno
asin(x) arco seno
atan(x) arco tangente
atan2(x,y) componente angular de la representación polar de x,y
ceil(x) menor entero mayor que x
cos(x) coseno
exp(x) e<SUP>x
</SUP>floor(x) mayor entero menor que x
IEEEremainder(x,y) resto de la división x/y según el estándar IEEE 754
log(x) logaritmo natural
max(x,y) el mayor de x e y
min(x,y) el menor de x e y
pow(x,y) x<SUP>y
</SUP>random() número aleatorio entre 0 y 1
rint(x) entero más cercano a x (devuelve un doble)
round(x) entero más cercano a x (devuelve un entero o un long)
sin(x) seno
sqrt(x) raíz cuadrada
tan(x) tangente</FONT>
</PRE>
<P>
Algunos de estos métodos disparan <I>excepciones</I>, como
<FONT FACE="Arial">sqrt</FONT> o <FONT FACE="Arial">log</FONT>
de números negativos. Más adelante veremos cómo
se usan las excepciones.
<P>
Otra clase que hemos estado usando mucho es la <FONT FACE="Arial">PrintStream</FONT>,
a la que pertenece el método <FONT FACE="Arial">println</FONT>.
En
<PRE>
<FONT SIZE=2> System.out.println(...)</FONT>
</PRE>
<P>
<FONT FACE="Arial">out</FONT> es un <I>atributo</I> de la clase
<FONT FACE="Arial">System</FONT>, del tipo (clase)<FONT FACE="Arial">
PrintStream</FONT>:
<PRE>
<FONT SIZE=2>public final class System extends Object
{
// Fields
public static PrintStream err;
public static InputStream in;
public static PrintStream out;
// Methods
.............
}</FONT>
</PRE>
<P>
Veremos otras bibliotecas (para entrada/salida, gráficos,
etc) muy pronto. Nos vemos en el capítulo VII.
<BR>
<HR>
<P>
Jorge Bourdette
<P>
<A HREF="mailto:jpb@amarillas.com">jpb@amarillas.com</A>
</BODY>
</HTML>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -