Anda di halaman 1dari 19

Sobrecarga de Mtodos.

En Java es posible definir dos o ms mtodos dentro de la misma clase que comparten el mismo
nombre, siempre y cuando sus declaraciones de parmetro son diferentes. Cuando esto sucede,
los mtodos se dicen a sobrecargarse, y el proceso se conoce como la sobrecarga de mtodos.
Sobrecarga de mtodos es una de las maneras que Java implementa el polimorfismo. Si nunca ha
utilizado un lenguaje que permite la sobrecarga de mtodos y, a continuacin, el concepto puede
parecer extrao al principio. Pero como puede ver, sobrecarga de mtodos es una de las
caractersticas ms interesantes y tiles de Java. Cuando se invoca un mtodo sobrecargado, Java
utiliza el tipo o el nmero de argumentos como su gua para determinar la versin del mtodo
sobrecargado realmente llamar. Por lo tanto, los mtodos sobrecargados deben ser diferente en el
tipo o el nmero de sus parmetros. Aunque los mtodos sobrecargados pueden tener diferentes
tipos de devolucin, el tipo devuelto por s sola no basta distinguir dos versiones de un mtodo.
Cuando Java encuentra una llamada a un mtodo sobrecargado, simplemente ejecuta la versin
del mtodo cuyos parmetros coincidan con los argumentos utilizados en la llamada. Aqu est un
ejemplo sencillo que ilustra la sobrecarga de mtodos:
// Demonstrate method overloading.
class OverloadDemo {
void test() {
System.out.println("No parameters");
}
// Overload test for one integer parameter.
void test(int a) {
System.out.println("a: " + a);
}
// Overload test for two integer parameters.
void test(int a, int b) {
System.out.println("a and b: " + a + " " + b);
}
// overload test for a double parameter
double test(double a) {
System.out.println("double a: " + a);
return a*a;
}
}
class Overload {
public static void main(String args[]) {
OverloadDemo ob = new OverloadDemo();
double result;
// call all versions of test()
ob.test();
ob.test(10);
ob.test(10, 20);
result = ob.test(123.25);
System.out.println("Result of ob.test(123.25): " + result);
}
}
Este programa genera el siguiente resultado:
No parameters
a: 10
a and b: 10 20
double a: 123.25
Result of ob.test(123.25): 15190.5625
Como puede ver, (de prueba) est sobrecargado cuatro veces. La primera versin no toma
parmetros, la segunda toma un parmetro de nmero entero, la tercera toma dos parmetros de
enteros, y la cuarta toma un parmetro doble. El hecho de que la cuarta versin de prueba ()
tambin devuelve un valor es sin consecuencias respecto a la sobrecarga, ya que tipos de
devolucin no desempear un papel en la resolucin de sobrecarga. Cuando se llama a un mtodo
sobrecargado, Java busca una coincidencia entre los argumentos utilizados para llamar el mtodo
y los parmetros del mtodo. Sin embargo, este partido no siempre necesita ser exacto. En
algunos casos las conversiones de tipo automtico de Java pueden desempear un papel en la
resolucin de sobrecarga. Por ejemplo, considere el siguiente programa:
// Automatic type conversions apply to overloading.
class OverloadDemo {
void test() {
}
// Overload test for two integer parameters.
void test(int a, int b) {
System.out.println("a and b: " + a + " " + b);
}
// overload test for a double parameter
void test(double a) {
System.out.println("Inside test(double) a: " + a);
}
}
class Overload {
public static void main(String args[]) {
OverloadDemo ob = new OverloadDemo();
int i = 88;
ob.test();
ob.test(10, 20);
ob.test(i); // this will invoke test(double)
ob.test(123.2); // this will invoke test(double)
}
}
Este programa genera el siguiente resultado:
No parameters
a and b: 10 20
Inside test(double) a: 88
Inside test(double) a: 123.2
Como puede ver, esta versin de OverloadDemo no define test(int). Por lo tanto, cuando se llama
a prueba () con un argumento entero dentro de sobrecarga, no se encuentra ningn mtodo
coincidente. Sin embargo, Java puede convertir automticamente un nmero entero en un doble,
y esta conversin puede utilizarse para resolver la llamada. Por lo tanto, despus de que no se
encuentra test(int), Java me eleva a doble y, a continuacin, llama test(double). Por supuesto, si
test(int) se haba definido, se habra llamado en su lugar. Java emplear sus conversiones de tipo
automtico slo si no se encuentra ninguna coincidencia exacta. Sobrecarga de mtodos soporta
polimorfismo porque es una manera de que Java implementa el paradigma de "una interfaz, varios
mtodos". Para entender cmo, considere lo siguiente. En lenguajes que no admiten la sobrecarga
de mtodos, debe darse un nombre nico a cada mtodo. Sin embargo, con frecuencia se desea
implementar esencialmente el mismo mtodo para diferentes tipos de datos. Considrese la
funcin valor absoluto. En lenguajes que no admiten la sobrecarga, generalmente hay tres o ms
versiones de esta funcin, cada uno con un nombre ligeramente diferente. Por ejemplo, en el C, el
abs de funcin () devuelve el valor absoluto de un nmero entero, laboratorios () devuelve el valor
absoluto de un entero largo y fabulosos () devuelve el valor absoluto de un valor de coma flotante.
Ya c no admite la sobrecarga, cada funcin debe tener su propio nombre, a pesar de todas las
funciones de tres es esencialmente la misma cosa.
Esto hace la situacin ms compleja, conceptualmente, lo que realmente es. Aunque el concepto
subyacente de cada funcin es el mismo, todava tiene tres nombres para recordar. Esta situacin
se produce en Java, porque cada mtodo de valor absoluto puede utilizar el mismo nombre. De
hecho, la biblioteca de clase estndar de Java incluye un mtodo de valor absoluto, llamado abs ().
Este mtodo est sobrecargado por la clase de matemticas de Java para manejar todos los tipos
numricos. Java determina qu versin de abs () para llamar a basada en el tipo de argumento. El
valor de la sobrecarga es que permite que los mtodos relacionados a ser visitada por el uso de un
nombre comn. As, el nombre abs representa la accin de carcter general que se est
realizando. Se deja al compilador para elegir la versin derecho especfica para una circunstancia
particular. Usted, el programador, necesita slo recordar la operacin general que se realiza. A
travs de la aplicacin de polimorfismo, varios nombres han sido reducidos a uno. Aunque este
ejemplo es bastante simple, que si expande el concepto, puede ver cmo puede ayudar la
sobrecarga, administrar la mayor complejidad.
Cuando usted sobrecarga un mtodo, cada versin de dicho mtodo puede realizar cualquier
actividad que desee. No hay regla que indica que los mtodos sobrecargados deben relacionar
entre s. Sin embargo, desde un punto de vista estilstico, la sobrecarga de mtodos implica una
relacin. As, mientras que se puede utilizar el mismo nombre para sobrecargar mtodos no
relacionados, usted no debe. Por ejemplo, se podra utilizar el nombre sqr para crear mtodos que
devuelven el cuadrado de un nmero entero y la raz cuadrada de un valor de coma flotante. Pero
estas dos operaciones son fundamentalmente diferentes. Aplicar el mtodo de la sobrecarga en
derrotas de esta manera su propsito original. En la prctica, slo se deben sobrecargar las
operaciones estrechamente relacionadas.
Sobrecarga de Constructors.
Adems de la sobrecarga de mtodos normales, tambin puede sobrecargar mtodos de
constructor. De hecho, para la mayora las clases reales que cree, constructores sobrecargados
ser la norma, no la excepcin. Para entender por qu, volvamos a la clase de cuadro desarrollada
en el captulo anterior. Lo que sigue es la ltima versin del cuadro:
class Box {
double width;
double height;
double depth;
// This is the constructor for Box.
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
Como se puede ver, el Box( ) constructor requiere tres parmetros. Esto significa que todas las
declaraciones de un cuadro de objetos deben pasar tres argumentos para el constructor de box ().
Por ejemplo, la siguiente declaracin es actualmente no vlida:

Box ob = new Box();
Box( ) requiere tres argumentos, es un error llamarlo sin ellos. Esto plantea algunas cuestiones
importantes. Qu sucede si simplemente quera un cuadro y no cuidado (o saber) lo que fueron
sus dimensiones iniciales? O, qu sucede si desea poder inicializar un cubo mediante la
especificacin de un nico valor que se utilizara para las tres dimensiones? Como la clase de
cuadro actualmente est escrita, estas otras opciones no estn disponibles para usted.
Afortunadamente, la solucin a estos problemas es muy fcil: simplemente de sobrecarga del
constructor de cuadro para que maneja las situaciones que se acaba de describir. Aqu es un
programa que contiene una versin mejorada del cuadro que hace exactamente eso:

/* Here, Box defines three constructors to initialize
the dimensions of a box various ways.
*/
class Box {
double width;
double height;
double depth;
// constructor used when all dimensions specified
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// constructor used when no dimensions specified
Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}
// constructor used when cube is created
Box(double len) {
width = height = depth = len;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
class OverloadCons {
public static void main(String args[]) {
// create boxes using the various constructors
Box mybox1 = new Box(10, 20, 15);
Box mybox2 = new Box();
Box mycube = new Box(7);
double vol;
// get volume of first box
vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
// get volume of second box
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
// get volume of cube
vol = mycube.volume();
System.out.println("Volume of mycube is " + vol);
}
}
Aqu se muestra la salida producida por este programa:
Volume of mybox1 is 3000.0
Volume of mybox2 is -1.0
Volume of mycube is 343.0
Como puede ver, se llama al constructor sobrecargado adecuado en funcin de los parmetros
especificados cuando se ejecuta en nuevo.
Uso de objetos como parmetros
Hasta ahora hemos slo se ha utilizando tipos simples como parmetros a los mtodos. Sin
embargo, es correcto y comn para pasar objetos a mtodos. Por ejemplo, considere el siguiente
programa corto:
// Objects may be passed to methods.
class Test {
int a, b;
Test(int i, int j) {
a = i;
b = j;
}
// return true if o is equal to the invoking object
boolean equals(Test o) {
if(o.a == a && o.b == b) return true;
else return false;
}
}
class PassOb {
public static void main(String args[]) {
Test ob1 = new Test(100, 22);
Test ob2 = new Test(100, 22);
Test ob3 = new Test(-1, -1);
System.out.println("ob1 == ob2: " + ob1.equals(ob2));
System.out.println("ob1 == ob3: " + ob1.equals(ob3));
}
}
Este programa genera el siguiente resultado:
ob1 == ob2: true
ob1 == ob3: false

Como puede ver, el mtodo equals de () dentro de prueba compara dos objetos para la igualdad y
devuelve el resultado. Es decir, compara el objeto invocando con uno que se pasa. Si contienen los
mismos valores, el mtodo devuelve true. De lo contrario, devuelve false. Observe que el
parmetro o es igual a () especifica la prueba como su tipo. Aunque la prueba es un tipo de clase
creado por el programa, se utiliza en slo del mismo modo que los tipos integrados de Java. Uno
de los usos ms comunes de los parmetros del objeto implica constructores. Frecuentemente se
desea construir un nuevo objeto, por lo que inicialmente es el mismo que algn objeto existente.
Para ello, debe definir un constructor que toma un objeto de su clase como un parmetro. Por
ejemplo, la siguiente versin del cuadro de permite que un objeto inicializar otro:
// Here, Box allows one object to initialize another.
class Box {
double width;
double height;
double depth;
// construct clone of an object
Box(Box ob) { // pass object to constructor
width = ob.width;
height = ob.height;
depth = ob.depth;
}
// constructor used when all dimensions specified
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// constructor used when no dimensions specified
Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}
// constructor used when cube is created
Box(double len) {
width = height = depth = len;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
class OverloadCons2 {
public static void main(String args[]) {
// create boxes using the various constructors
Box mybox1 = new Box(10, 20, 15);
Box mybox2 = new Box();
Box mycube = new Box(7);
Box myclone = new Box(mybox1);
double vol;
// get volume of first box
vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
// get volume of second box
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
// get volume of cube
vol = mycube.volume();
System.out.println("Volume of cube is " + vol);
// get volume of clone
vol = myclone.volume();
System.out.println("Volume of clone is " + vol);
}
}
Como puede ver cuando comience a crear sus propias clases, proporcionando muchas formas de
mtodos de constructor normalmente es necesario para permitir que los objetos que se
construirn en una manera conveniente y eficiente.

Un vistazo a pasar argumento.
En general, hay dos maneras de que un lenguaje de programacin puede pasar un argumento a
una subrutina. La primera es llamada por valor. Este mtodo copia el valor de un argumento en el
parmetro formal de la subrutina. Por lo tanto, los cambios realizados en el parmetro de la
subrutina no tienen efecto sobre el argumento. La segunda manera que puede pasar un
argumento es llamada por referencia. En este mtodo, se pasa una referencia a un argumento (no
el valor del argumento) para el parmetro. Dentro de la subrutina, esta referencia se utiliza para
acceder el argumento real especificado en la llamada. Esto significa que los cambios realizados en
el parmetro afectar el argumento que se utiliza para llamar a la subrutina. Como puede ver, Java
utiliza ambos enfoques, en funcin de lo que se pasa. En Java, al pasar un tipo simple a un mtodo,
se pasa por valor. Por lo tanto, lo que se produce al parmetro que recibe el argumento no tiene
efecto fuera del mtodo. Por ejemplo, considere el siguiente programa:
// Simple types are passed by value.
class Test {
void meth(int i, int j) {
i *= 2;
j /= 2;
}
}
class CallByValue {
public static void main(String args[]) {
Test ob = new Test();
int a = 15, b = 20;
System.out.println("a and b before call: " +
a + " " + b);
ob.meth(a, b);
System.out.println("a and b after call: " +
a + " " + b);
}
}
La salida de este programa se muestra aqu:
a and b before call: 15 20
a and b after call: 15 20
Como puede ver, las operaciones que se producen dentro de meth() no tienen ningn efecto en
los valores de un y b utilizado en la llamada; sus valores aqu no cambi a 30 y 10. Cuando se pasa
un objeto a un mtodo, la situacin cambia drsticamente, debido a que los objetos se pasan por
referencia. Tenga en cuenta que cuando se crea una variable de un tipo de clase, slo se crea una
referencia a un objeto. As, cuando se pasa esta referencia a un mtodo, el parmetro que recibe
se referir al mismo objeto como la que se refiri el argumento. Esto significa que los objetos se
pasan a los mtodos por uso de llamada por referencia. Cambios en el objeto dentro del mtodo
afectan al objeto que se utiliza como argumento. Por ejemplo, considere el siguiente programa:
// Objects are passed by reference.
class Test {
int a, b;
Test(int i, int j) {
a = i;
b = j;
}
// pass an object
void meth(Test o) {
o.a *= 2;
o.b /= 2;
}
}
class CallByRef {
public static void main(String args[]) {
Test ob = new Test(15, 20);
System.out.println("ob.a and ob.b before call: " +
ob.a + " " + ob.b);
ob.meth(ob);
System.out.println("ob.a and ob.b after call: " +
ob.a + " " + ob.b);
}
}
Este programa genera el siguiente resultado:
ob.a and ob.b before call: 15 20
ob.a and ob.b after call: 30 10
Como puede ver, en este caso, las acciones () de metanfetaminas han afectado el objeto utilizado
como argumento. Como un punto de inters, cuando una referencia de objeto se pasa a un
mtodo, la propia referencia se pasa por el uso de la llamada por valor. Sin embargo, dado que el
valor que se pasa se refiere a un objeto, la copia de ese valor todava se referir al mismo objeto
que hace de su argumento correspondiente.
Returning Objects
Un mtodo puede devolver cualquier tipo de datos, incluidos los tipos de clase que se crean. Por
ejemplo, el siguiente programa, el mtodo de incrByTen () devuelve un objeto en el que el valor de
un diez es mayor que en el objeto invocando.
// Returning an object.
class Test {
int a;
Test(int i) {
a = i;
}
Test incrByTen() {
Test temp = new Test(a+10);
return temp;
}
}
class RetOb {
public static void main(String args[]) {
Test ob1 = new Test(2);
Test ob2;
ob2 = ob1.incrByTen();
System.out.println("ob1.a: " + ob1.a);
System.out.println("ob2.a: " + ob2.a);
ob2 = ob2.incrByTen();
System.out.println("ob2.a after second increase: "
+ ob2.a);
}
}
Aqu se muestra la salida generada por este programa:
ob1.a: 2
ob2.a: 12
ob2.a after second increase: 22
Como puede ver, se invoca cada () incrByTen de tiempo, se crea un nuevo objeto y, a
continuacin, se devuelve una referencia a la misma a la rutina de llamada. El programa anterior
hace otro punto importante: ya que todos los objetos se asignan dinmicamente utilizando de
nuevo, no es necesario preocuparse por un objeto que se va fuera de mbito, porque termina el
mtodo en el que fue creado. El objeto seguir existiendo mientras hay una referencia a l en
alguna parte de su programa. Cuando no hay referencias a l, el objeto se ser reclamado la
prxima vez que lleva a cabo la recoleccin




Recursion.
Java soporta la recursividad. Recursin es el proceso de definir algo de s mismo. Lo que se refiere
a la programacin Java, recursin es el atributo que permite un mtodo para llamar a s mismo. Un
mtodo que se llama a s mismo se dice que es recursiva. El ejemplo clsico de la recursividad es el
cmputo del factorial de un nmero. El factorial de un nmero n es el producto de todos los
nmeros enteros entre 1 y N. Por ejemplo, 3 factorial es 1 2 3 o 6. Aqu es cmo puede
calcularse un factorial por uso de un mtodo recursivo:

// A simple example of recursion.
class Factorial {
// this is a recursive function
int fact(int n) {
int result;
if(n==1) return 1;
result = fact(n-1) * n;
return result;
}
}
class Recursion {
public static void main(String args[]) {
Factorial f = new Factorial();
System.out.println("Factorial of 3 is " + f.fact(3));
System.out.println("Factorial of 4 is " + f.fact(4));
System.out.println("Factorial of 5 is " + f.fact(5));
}
}
La salida de este programa se muestra aqu:
Factorial of 3 is 6
Factorial of 4 is 24
Factorial of 5 is 120
Si no est familiarizado con los mtodos recursiva, la operacin de hecho () puede parecer un poco
confusa. Aqu es cmo funciona. Cuando se llama (de hecho) con un argumento de 1, la funcin
devuelve 1; de lo contrario devuelve el producto de hecho (n1) * n. Para evaluar esta expresin,
(de hecho) se llama con n1. Este proceso se repite hasta que n es igual a 1 y las llamadas al
mtodo comienzan a regresar.
Para entender mejor cmo funciona el mtodo () de hecho, vamos a travs de un ejemplo corto.
Cuando se calcula el factorial de 3, la primera llamada a (de hecho) har una segunda llamada a
hacerse con un argumento de 2. Esta invocacin causar (de hecho) a ser llamada una tercera vez
con un argumento de 1. Esta llamada devuelve 1, que luego se multiplica por 2 (el valor de n en la
invocacin del segunda). Este resultado (2), a continuacin, se volvi a la invocacin original de (de
hecho) y multiplicado por 3 (el valor original de n). Esto da la respuesta, 6. Puede ser interesante
insertar las declaraciones de Console.println () en (de hecho) que mostrar el nivel de cada
llamada y cules son las respuestas intermedias.
Cuando un mtodo llama a s mismo, parmetros y variables locales nuevas estn asignados a
almacenamiento de informacin en la pila y se ejecuta el cdigo del mtodo con estas nuevas
variables desde el principio. Una llamada recursiva no hace una copia nueva del mtodo. Slo los
argumentos son nuevos. Como cada llamada recursiva devuelve, los parmetros y variables locales
antiguas se quitan de la pila y se reanuda la ejecucin en el momento de la llamada dentro del
mtodo. Mtodos de recursiva pueden decirse que "telescopio" fuera y de vuelta. Versiones de
recursiva de muchas rutinas pueden ejecutar un poco ms lentamente que el equivalente iterativo
debido a la mayor sobrecarga de las llamadas a funciones adicionales. Muchas llamadas recursivas
a un mtodo podran causar un desbordamiento de la pila. Porque es de almacenamiento para los
parmetros y las variables locales en la pila y cada nueva llamada crea una nueva copia de estas
variables, es posible que la pila podra estar agotada. Si esto ocurre, el sistema de tiempo de
ejecucin de Java producir una excepcin. Sin embargo, probablemente no tendr que
preocuparse por esto a menos que una rutina recursiva se ejecuta silvestre.
La ventaja principal de mtodos recursivo es que se puede utilizar para crear versiones ms claras
y sencillas de varios algoritmos que sus parientes iterativos. Por ejemplo, el algoritmo de
ordenacin QuickSort es bastante difcil de implementar de forma iterativa. Algunos problemas,
especialmente relacionados con AI ms, parecen que se prestan a soluciones recursiva. Por ltimo,
algunas personas parecen pensar ms fcilmente que iterativamente de forma recursiva. Al
escribir mtodos recursiva, debe tener un si en algn lugar de instruccin para forzar el mtodo
para volver sin la llamada recursiva que se est ejecutando. Si no haces esto, una vez que se llama
al mtodo, nunca volver. Esto es un error muy comn en el trabajo con la recursividad. Utilice
Console.println () declaraciones liberalmente durante el desarrollo para que usted puede ver lo
que est sucediendo y abortar la ejecucin si ves que ha cometido un error.
Aqu es un ejemplo ms de la recursividad. El printArray de mtodo recursivo () imprime la
primera me elementos en los matriz de valores.
// Another example that uses recursion.
class RecTest {
int values[];
RecTest(int i) {
values = new int[i];
}
// display array -- recursively
void printArray(int i) {
if(i==0) return;
else printArray(i-1);
System.out.println("[" + (i-1) + "] " + values[i-1]);
}
}
class Recursion2 {
public static void main(String args[]) {
RecTest ob = new RecTest(10);
int i;
for(i=0; i<10; i++) ob.values[i] = i;
ob.printArray(10);
}
}
Este programa genera el siguiente resultado:
[0] 0
[1] 1
[2] 2
[3] 3
[4] 4
[5] 5
[6] 6
[7] 7
[8] 8
[9] 9

Anda mungkin juga menyukai