NOMBRE: FCO. JAVIER VAZQUEZ PANTALEON. CARRERA: INGENIERIA EN SISTEMAS COMPUTACIONALES. SCHOOL: INSTITUTO TECNOLOGICO DE LAZARO CARDENAS MICHOACAN.

->MEXICO<- ->ARGENTINA<- ->ESPAÑA<-

Reproductor


Ringtones
Reproductor Mi musica ... en ...

martes, 15 de septiembre de 2009

Implementación de Métodos

Similarmente a la implementación de una clase, la implementación de un método consiste en dos
partes, la declaración y el cuerpo del método.
declaracióndeMétodo {
cuerpodeMétodo
}

La Declaración de Método
Una declaración de método proporciona mucha información sobre el método al
compilador, al sistema en tiempo de ejecución y a otras clases y objetos. Junto con el
nombre del método, la declaración lleva información como el tipo de retorno del
método, el número y el tipo de los argumentos necesarios, y qué otras clases y objetos
pueden llamar al método.
Los únicos elementos necesarios una declaración de método son el nombre y el tipo de
retorno del método.

Por ejemplo, el código siguiente declara un método llamado
estaVacio() en la clase Pila que devuelve un valor booleano (true o false):
class Pila {
. . .
boolean estaVacio() {
. . .
}
}
Devolver un Valor desde un Método
Java necesita que un método declare el tipo de dato del valor que devuelve. Si un
método no devuelve ningún valor, debe ser declarado para devolver void (nulo).
Los métodos pueden devolver tipos de datos primitivos o tipos de datos de referencia. El
método estaVacio() de la clase Pila devuelve un tipo de dato primitivo, un valor
booleano:
class Pila {
static final int PILA_VACIA = -1;
Object[] stackelements;
int topelement = PILA_VACIA;
. . .
boolean estaVacio() {
if (topelement == PILA_VACIA)
return true;
else
return false;
}
}
Sin embargo, el método pop de la clase PILA devuelve un tipo de dato de referencia: un
objeto.
class Pila {
static final int PILA_VACIA = -1;
Object[] stackelements;
int topelement = PILA_VACIA;
. . .
Object pop() {
if (topelement == PILA_VACIA)
return null;
else {
return stackelements[topelement--];
}
}
}
Los métodos utilizan el operador return para devolver un valor. Todo método que no
sea declarado como void debe contener una sentencia return.
El tipo de dato del valor devuelto por la sentencia return debe corresponder con el tipo
de dato que el método tiene que devolver; no se puede devolver un objeto desde un
método que fue declarado para devolver un entero.
Cuando se devuelva un objeto, el tipo de dato del objeto devuelto debe ser una
subclase o la clase exacta indicada. Cuando se devuelva un tipo interface, el objeto
retornado debe implementar el interface especificado.
Un Nombre de Método
Un nombre de método puede ser cualquier indentificador legal en Java. Existen tres
casos especiales a tener en cuenta con los nombres de métodos:
Java soporta la sobrecarga de métodos, por eso varios métodos pueden compartir
el mismo nombre. Por ejemplo, supon que se ha escrito una clase que puede
proporcionar varios tipos de datos (cadenas, enteros, etc...) en un área de dibujo.
Se podría escribir un método que supiera como tratar a cada tipo de dato. En otros
lenguajes, se tendría que pensar un nombre distinto para cada uno de los
métodos. dibujaCadena(), dibujaEntero, etc... En Java, se puede utilizar el
mismo nombre para todos los métodos pasándole un tipo de parámetro diferente a
cada uno de los métodos. Entonces en la clase de dibujo, se podrán declarar tres
métodos llamados draw<() y que cada uno aceptara un tipo de parámetro
diferente:
class DibujodeDatos {
void draw(String s) {
. . .
}
void draw(int i) {
. . .
}
void draw(float f) {
. . .
}
}
Nota: La información que hay dentro de los paréntesis de la declaración son los
argumentos del método. Los argumentos se cubren en la siguiente página: Pasar
Información a un Método.
Los métodos son diferenciados por el compilador basándose en el número y tipo de
sus argumentos. Así draw(String s)y draw(int i) son métodos distintos y únicos.
No se puede declarar un método con la misma firma: draw(String s)y
draw(String t) son idénticos y darán un error del compilador.
Habrás observado que los métodos sobrecargados deben devolver el mismo tipo de
1.
dato, por eso void draw(String s) y int draw(String t) declarados en la misma
clase producirán un error en tiempo de compilación.
Todo método cuyo nombre sea igual que el de su clase es un constructor y tiene
una tarea especial que realizar. Los constructores se utilizan para inicializar un
objeto nuevo del tipo de la clase. Los constructores sólo pueden ser llamados con
el operador new. Para aprender cómo escribir un constructor, puedes ver Escribir
un Método Constructor.
2.
Una clase puede sobreescribir un método de sus superclases. El método que
sobreescribe debe tener el mismo, nombre, tipo de retorno y lista de parámetros
que el método al que ha sobreescrito. Sobreescribir Métodos te enseñará como
sobreescribir los métodos de una superclase.
3.
Caractersiticas Avanzadas de la Declaración de Métodos
Junto con los dos elementos necesarios, una declaración de método puede contener
otros elementos. Estos elementos declaran los argumentos aceptados por el método, si
el método es un método de clase, etc...
Juntándolo todo, una declaración de método se parecería a esto:
[especificadordeAcceso] [static] [abstract] [final] [native] [synchronized]
tipodeRetorno nombredelMétodo ([listadeparámetros]) [throws listadeExcepciones]
Cada uno de estos elementos de una declaración se cubre en alguna parte de este
tutorial.

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 varibales delimitadas por comas donde cada declaración de varibale 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 dento del cuerpo del método para referise 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ñas, 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 varibales 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 tavé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 seran 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 varibales 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 metodo 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.

El Cuerpo del Método
En el siguiente ejemplo, el cuerpo de método para los métodos estaVacio() y
poner() están en negrita:
class Stack {
static final int PILA_VACIA = -1;
Object[] elementosPila;
int elementoSuperior = PILA_VACIA;
. . .
boolean estaVacio() {
if (elementoSuperior == PILA_VACIA)
return true;
else
return false;
}
Object poner() {
if (elementoSuperior == PILA_VACIA)
return null;
else {
return elementosPila[elementoSuperior--];
}
}
}
Junto a los elementos normales del lenguaje Java, se puede utilizar this en el
cuerpo del método para referirse a los miembros del objeto actual. El objeto actual
es el objeto del que uno de cuyos miembros está siendo llamado. También se
puede utilizar super para referirse a los miembros de la superclase que el objeto
actual haya ocultado mediante la sobreescritura. Un cuerpo de método también
puede contener declaraciones de variables que son locales de ese método.
this
Normalmente, dentro del cuerpo de un método de un objeto se puede
referir directamente a las variables miembros del objeto. Sin embargo,
algunas veces no se querrá tener ambiguedad sobre el nombre de la
variable miembro y uno de los argumentos del método que tengan el
mismo nombre.
Por ejemplo, el siguiente constructor de la clase HSBColor inicializa
alguna variable miembro de un objeto de acuerdo a los argumentos
pasados al constructor. Cada argumento del constructor tiene el mismo
nombre que la variable del objeto cuyo valor contiene el argumento.
class HSBColor {
int hue, saturacion, brillo;
HSBColor (int luminosidad, int saturacion, int brillo) {
this.luminosidad = luminosidad;
this.saturacion = saturacion;
this.brillo = brillo;
}
}
Se debe utilizar this en este constructor para evitar la embiguedad entre
el argumento luminosidad y la variable miembro luminosidad (y así
con el resto de los argumentos). Escribir luminosidad = luminosidad;
no tendría sentido. Los nombres de argumentos tienen mayor
precedencia y ocultan a los nombres de las variables miembro con el
mismo nombre. Para referirise a la variable miembro se debe hacer
explicitamente a través del objeto actual--this.
También se puede utilizar this para llamar a uno de los métodos del
objeto actual. Esto sólo es necesario si existe alguna ambigüedad con el
nombre del método y se utiliza para intentar hacer el código más claro.
super
Si el método oculta una de las variables miembro de la superclase, se
puede referir a la variable oculta utilizando super. De igual forma, si el
método sobreescribe uno de los métodos de la superclase, se puede
llamar al método sobreescrito a través de super.
Consideremos esta clase:
class MiClase {
boolean unaVariable;
void unMetodo() {
unaVariable = true;
}
}
y una subclase que oculta unaVariable y sobreescribe unMetodo():
class OtraClase extends MiClase {
boolean unaVariable;
void unMetodo() {
unaVariable = false;
super.unMetodo();
System.out.println(unaVariable);
System.out.println(super.unaVariable);
}
}
Primero unMetodo() selecciona unaVariable (una declarada en
OtraClase que oculta a la declarada en MiClase) a false. Luego
unMetodo() llama a su método sobreescrito con esta sentencia:
super.unMetodo();
Esto selecciona la versión oculta de unaVariable (la declarada en
MiClase) a true. Luego unMetodo muestra las dos versiones de
unaVariable con diferentes valores:
false
true
Variables Locales
Dentro del cuerpo de un método se puede declarar más variables para
usarlas dentro del método. Estas variables son variables locales y viven
sólo mientras el control permanezca dentro del método. Este método
declara un variable local i y la utiliza para operar sobre los elementos del
array.
Object encontrarObjetoEnArray(Object o, Object[] arrayDeObjetos) {
int i; // variable local
for (i = 0; i < arrayDeObjetos.length; i++) {
if (arrayDeObjetos[i] == o)
return o;
}
return null;
}
Después de que este método retorne, i ya no existirá más.

No hay comentarios:

Publicar un comentario