Pasar Información a un Método.
Cuando se escribe un método, se
declara el número y tipo de los argumentos requeridos por ese método. Esto se
hace en la firma del método. Por ejemplo, el siguiente método calcula el pago mensual
de una hipoteca basándose en la cantidad prestada, el interés, la duración de
la hipoteca (número de meses) y el valor futuro de la hipoteca (presumiblemente
el valor futuro sea cero, porque al final de la hipoteca, ya la habrás pagado):
double hipoteca(double cantidad,
double interes, double valorFinal, int numPeriodos)
{
double I, parcial1, denominador, respuesta;
I = interes / 100.0;
parcial1 = Math.pow((1 + I), (0.0 - numPeriodos));
denominador = (1 - parcial1) / I;
respuestar = ((-1 * cantidad) / denominador) - ((valorFinal * parcial1)
/
denominador);
return respuesta;
}
Este método toma cuatro argumentos: la
cantidad prestada, el interés, el valor futuro y el número de meses. Los tres
primeros son números de coma flotante de doble precisión y el cuarto es un entero.
Al igual que este método, el conjunto
de argumentos de cualquier método es una lista de declaraciones de variables
delimitadas por comas donde cada declaración de variable es un par tipo/nombre:
tipo nombre
Como has podido ver en el ejemplo
anterior, sólo tienes que utilizar el nombre del argumento para referirte al
valor del argumento.
Tipos
de Argumentos
En Java, se puede
pasar como argumento a un método cualquier tipo de dato válido en Java. Esto
incluye tipos primitivos, como enteros, dobles, etc.. y tipos de referencia
como arrays, objetos, etc...
Aquí tienes un
ejemplo de un constructor que acepta una array como argumento. En este ejemplo
el constructor inicializa un objeto Polygon a partir de una lista de puntos
(Point es una clase del paquete java.awt que representa una coordenada xy):
Polygon polygonFrom(Point[]
listadePuntos) {
. . .
}
Al contrario que en otros lenguajes, no se
puede pasar un método a un método Java. Pero
si se podría pasar un objeto a un método y
luego llamar a los métodos del objeto.
Nombres
de Argumentos
Cuando se declara un argumento para un
método Java, se proporciona el nombre para ese argumento. Este nombre es
utilizado dentro del cuerpo del método para referirse al valor del argumento.
Un argumento de un método puede tener
el mismo nombre que una variable de la clase.
En este caso, se dice que el argumento
oculta a la variable miembro. Normalmente los argumentos que ocultan una
variable miembro se utilizan en los constructores para inicializar una clase.
Por ejemplo, observa la clase Circle y su constructor:
class Circle {
int
x, y, radius;
public
Circle(int x, int y, int radius) {
. . .
}
}
La clase Circle tiene tres
variables miembro x, y y radius. Además, el constructor de
la clase Circle acepta tres argumentos cada uno de los cuales comparte el
nombre con la variable miembro para la que el argumento proporciona un valor
inicial.
Los nombres de argumentos
ocultan los nombres de las variables miembro. Por eso utilizar x, y o
radius dentro del cuerpo de la función, se refiere a los argumentos, no
a las variables miembro. Para acceder a las variables miembro, se debe
referenciarlas a través de this--el objeto actual.
class Circle {
int
x, y, radius;
public
Circle(int x, int y, int radius) {
this.x
= x;
this.y
= y;
this.radius
= radius;
}
}
Los nombres de los
argumentos de un método no pueden ser el mismo que el de otros argumentos del
mismo método, el nombre de cualquier variable local del método o el nombre de
cualquier parámetro a una clausula catch() dentro del mismo método.
Paso por Valor
En los métodos Java, los argumentos
son pasados por valor. Cuando se le llama, el método recibe el valor de
la variable pasada. Cuando el argumento es de un tipo primitivo, pasar por
valor significa que el método no puede cambiar el valor. Cuando el argumento es
del tipo de referencia, pasar por valor significa que el método no puede
cambiar el objeto referenciado, pero si puede invocar a los métodos del objeto
y puede modificar las variables accesibles dentro del objeto.
Consideremos esta serie de sentencias
Java que intentan recuperar el color actual de un objeto Pen en una aplicación
gráfica:
. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("red =
" + r + ", green = " + g + ", blue = " + b);
. . .
En el momento que se llama al método getRGBColor(),
las variables r, g, y b tienen un valor de -1. El llamador espera que el método
getRGBColor() le devuelva los valores de rojo, verde y azul para el color
actual en las variables r, g, y b.
Sin embargo, el sistema Java pasa los
valores de las variables(-1) al método getRGBColor(); no una referencia a las
variables r, g, y b. Con esto se podría visualizar la llamada a getRGBColor() de
esta forma: getRGBColor(-1, -1, -1).
Cuando el control pasa dentro del
método getRGBColor(), los argumentos entran dentro del ámbito (se les asigna
espacio) y son inicializados a los valores pasados al método:
class
Pen {
int valorRojo,
valorVerde, valorAzul;
void getRGBColor(int
rojo, int verde, int azul) {
// rojo, verde y azul
han sido creados y sus valores son -1
. . .
}
}
Con esto getRGBColor() obtiene acceso a los valores de r,
g, y b del llamador a través de sus argumentos rojo, verde,
y azul, respectivamente. El método obtiene su propia copia de los
valores para utilizarlos dentro del ámbito del método. Cualquier cambio
realizado en estas copias locales no serán reflejados en las variables
originales del llamador.
Ahora veremos la implementación de getRGBColor() dentro de la
clase Pen que implicaba la firma de método anterior:
class
Pen {
int valorRojo,
valorVerde, valorAzul;
. . .
// Este método no
trabaja como se espera
void getRGBColor(int
rojo, int verde, int azul) {
rojo = valorRojo;
verde=valorVerde;
azul=valorAzul;
}
}
Este método no trabajará como se
espera. Cuando el control llega a la sentencia
println() en el siguiente fragmento de código, los argumentos rojo,
verde y azul de getRGBColor() ya no existen. Por lo tanto
las asignaciones realizadas dentro del método no tendrán efecto; r,
g, y b seguiran siendo igual a -1.
.
. .
int
r = -1, g = -1, b = -1;
pen.getRGBColor(r,
g, b);
System.out.println("rojo
= " + r + ", verde = " + g + ", azul = " + b);
. . .
El paso de las variables por valor le
ofrece alguna seguridad a los programadores: los métodos no puede modificar de
forma no intencionada una variable que está fuera de su ámbito. Sin embargo,
alguna vez se querrá que un método modifique alguno de sus argumentos. El método
getRGBColor() es un caso apropiado. El llamador quiere que el método
devuelva tres valores a través de sus argumentos. Sin embargo, el método no puede
modificar sus argumentos, y, además, un método sólo puede devolver un valor a través
de su valor de retorno. Entonces, ¿cómo puede un método devolver más de un valor,
o tener algún efecto (modificar algún valor) fuera de su ámbito?
Para que un método modifique un
argumento, debe ser un tipo de referencia como un objeto o un array. Los
objetos y arrays también son pasados por valor, pero el valor de un objeto es
una referencia. Entonces el efecto es que los argumentos de tipos de referencia
son pasados por referencia. De aquí el nombre. Una referencia a un objeto es la
dirección del objeto en la memoria. Ahora, el argumento en el método se refiere
a la misma posición de memoria que el llamador.
Reescribamos el método getRGBColor()
para que haga lo que queremos. Primero introduzcamos un nuevo objeto
RGBColor, que puede contener los valores de rojo, verde y azul de un color en
formato RGB:
class RGBColor {
public int rojo, verde,
azul;
}
Ahora podemos reescribir getRGBColor()
para que acepte un objeto RGBColor como argumento. El método getRGBColor()
devuelve el color actual de lápiz, en los valores de las variables miembro rojo,
verde y azul de su argumento RGBColor:
class Pen {
int valorRojo, valorVerde, valorAzul;
void getRGBColor(RGBColor unColor) {
unColor.rojo = valorRojo;
unColor.verde = valorVerde;
unColor.azul = valorAzul;
}
}
Y finalmente, reescribimos la secuencia de
llamada:
. . .
RGBColor penColor = new
RGBColor();
pen.getRGBColor(penColor);
System.out.println("ojo =
" + penColor.rojo + ", verde = " + penColor.verde + ",
azul = " + penColor.azul);
. . .
Las modificaciones realizadas al
objeto RGBColor dentro del método getRGBColor() afectan al objeto creado
en la secuencia de llamada porque los nombres penColor (en la secuencia
de llamada) y unColor (en el método getRGBColor()) se refieren al
mismo objeto.
No hay comentarios:
Publicar un comentario