You are on page 1of 5

Diario de un principiante (parte 4)

Mtodos y Clases en Java: Parte II


Continuamos en este artculo la discusin sobre aspectos ms avanzados de la POO en Java.

Introduccin: Polimorfismo en Java


Esta palabra que significa "muchas formas", es una caracterstica del lenguaje Java que permite a una interface ser usada por una clase general de acciones. La accin concreta a llevar a cabo se determina por la naturaleza especfica de la situacin. En trminos ms generales, el concepto de polimorfismo a menudo se expresa por la frase "una interfaz, mltiples mtodos". Esto significa que es posible disear una interfaz genrica para un grupo de actividades relacionadas. Es evidente que esta forma de trabajar ayuda a reducir la complejidad del diseo, pues permite usar una misma interfaz para especificar un conjunto de acciones similares. Ser el compilador el que tendr que seleccionar la accin concreta (esto es, el mtodo) para aplicar en cada situacin. Como programadores, nosotros solo tenemos que conocer la interfaz general. En el siguiente apartado se relata un caso prctico que ayudar a entender los beneficios del polimorfismo.

Sobrecarga de mtodos
Otra de las ventajas de este lenguaje de programacin es que nos permite definir dos o ms mtodos dentro de la misma clase con el mismo nombre, siempre que la declaracin de sus parmetros sea diferente. En este caso se dice que el mtodo est sobrecargado y el proceso de definir un mtodo as se conoce como sobrecarga del mtodo. La sobrecarga de mtodos es una de las maneras en que Java implementa el polimorfismo. Cuando se llama a un mtodo sobrecargado, el compilador acta justo sobre la versin cuyo tipo de parmetros coincida con los de la llamada. As, se podra definir la siguiente clase "SumaGenerica" que aglutinara las sumas de todos los tipos primitivos:
class SumaGenerica { int suma (int a, int b) { return a+b; } double suma (double a, double b) { return a+b; } ... }

NOTA: Realmente no sera necesario definir el mtodo suma() para todos los tipos de datos, pues aqu tambin interviene el casting implcito que hace Java. Por ejemplo, una suma de float, llamara automticamente al mtodo que devuelve double siempre y cuando no est definido el mtodo que devuelve float, claro est. No existe una regla exacta par saber si un mtodo se debe sobrecargar o no. Realmente, la idea es aprovechar las ventajas que ofrece esta forma de polimorfismo, as que lo normal es sobrecargar aquellos mtodos que estn intrnsicamente relacionados, como es el caso del ejemplo anterior pero no nos debemos confundir. Por ejemplo, el mtodo sqrt(), aunque se
1

http://www.javahispano.com

llama igual, calcula de forma totalmente diferente la raiz cuadrada de un nmero entero que la de uno en punto flotante. Aqu, aunque aplicaramos sobrecarga al mtodo, realmente no estaramos respetando el propsito para el que se cre el polimorfismo.

Sobrecarga de Constructores
Es aqu donde realmente se aprecia los beneficios del polimorfismo. Como sabemos, el constructor de una clase es el que inicializa los valores que el programador crea conveniente cuando sta se instancia. Pues bien, sobrecargando el constructor conseguimos dotar a la clase de flexibilidad. Por ejemplo, como mnimo se debera tener en cuenta que podra no pasarsele parmetros al constructor, cuando ste lo espera, debido a un fallo en alguna otra parte de la aplicacin (me refiero a cualquier otra clase que llame a sta). Es por ello que siempre es recomendable definir al menos dos constructores: el especfico de la aplicacin que estemos diseando y el "estndar". El siguiente ejemplo te lo va a dejar mucho ms claro:
class Box { double width; double height; double depth; //El siguiente es el constructor especfico Box(double w, double h, double d) { width = w; height = h; depth = d; } //pero podra ser que no le llegarn parmetros // por fallar la otra clase (mtodo) que lo invoque Box () { width = height = depth = -1 //-1 indica volumen no existente } //e incluso podemos pensar que se quiere construir un cubo, //entonces, por qu introducir 3 valores? ;) Box (double valor) { width = height = depth = valor; } double volume() { return width * height * depth; }

Como ves, de cara a flexibilizar una clase es fundamental el polimorfismo a la hora de implementar los constructores.

Objetos como parmetros


A parte de usar los tipos primitivos como parmetros, en Java es perfectamente posible pasarle a un mtodo un objeto como parmetro.
class Comparar { int a, b; Comparar (int i, int j) { a = i; b = j; } boolean equals (Comparar c) { if (c.a == a && c.b == b) return true; else return false; } 2

Diario de un principiante (parte 4)

Como se puede apreciar, el mtodo equals() de Comparar comprueba si dos objetos son idnticos . Esto es, compara el objeto que invoca el mtodo con el que se le pasa al mtodo como argumento. Acabo de liarte? ;), pues fjate en el siguiente trozo de cdigo que se explica mucho mejor.
class PasaObjeto { public static void main(string args[]) { Comparar objeto1 = new Test(2,3); Comparar objeto2 = new Test(2,3); System.out.println(objeto1.equals(objeto2)); } }

Como ves, objeto1 es el que invoca el mtodo y objeto2 es el que se pasa como argumento al mtodo equals() de objeto1. Observa tambin que el parmetro c en equals() especifica Comparar como tipo. Aunque Comparar es un tipo de clase creado por el programa, ste se usa de la misma manera que los tipos primitivos que Java nos proporciona.

Una mirada ms cercana al paso de argumentos


Como sabemos, existen dos formas de pasar un argumento a una rutina:

Por valor: El mtodo copia el valor de un argumento en el parmetro formal de la rutina. Por referencia: Se pasa al parmetro de la rutina la referencia al argumento (no su valor).

En el primer caso, al ser solo una copia, cualquier modificacin dentro de la rutina de ese valor no tendr efecto una vez fuera de ste mientras que si es por referencia, s persistir la modificacin hecha una vez salgamos de la rutina. Pues bien, cuando en Java se pasan argumentos de tipo simple, estos siempre se hacen por valor. Entonces, cmo puedo pasar un parmetro por referencia para modificarlo?. Pues muy fcil, pasando el objeto. Esto ocurre porque cuando tu creas una variable de un tipo de clase, tu solo creas una referencia al objeto. As, cuando pasas esta referencia a un mtodo, el parmetro que recibe ste se refiere al mismo objeto que el referido por el argumento. Por tanto, los cambios que se hagan en la referencia de la rutina afectarn tambin al objeto pasado como argumento.

El Operador static
Hay veces que se desea querer definir una clase miembro para ser usada independientemente de cualquier objeto de esa clase. Normalmente a una clase miembro se accede solo si hemos instanciado un objeto de dicha clase. No obstante, es posible crear un miembro que pueda ser usado por si mismo, sin necesidad de referenciar a una instancia especfica. Para crear tales tipos de miembros se emplea el operador static. Cuando un miembro se declara con esta palabra reservada, se puede acceder a l antes de que cualquier objeto de su clase sea creado, y sin referenciar a ningn objeto. Puedes declarar tanto los mtodos como las variables como static. El ejemplo ms claro de un miembro static
3

http://www.javahispano.com

es el main(). Se declara de esta manera porque se debe llamar antes de que cualquier objeto sea declarado.

Las variables static


Las variables de instancia declaradas como static (tambin llamadas "de clase ") son, esencialmente, variables globales. Cuando creamos objetos especficos de esa clase no se hace ninguna copia de las variables static. Lo que ocurre es que todas las instancias de esa clase comparten la misma variable static. Estas variables mayormente tienen sentido cuando varias instancias de la misma clase necesitan llevar el control o estado del valor de un dato. Tambin se podran utilizar para definir constantes, pero cuando menos es aconsejable que tambin se emplee el operador que se explica en la siguiente seccin. Para llamar a este tipo de variables se suele utilizar el nombre de la clase (no es imprescindible, pues se puede utilizar tambin el nombre de cualquier objeto), porque de esta forma queda ms claro, seguida de un "." y la variable, por ejemplo, Estatica.b Las variables miembro static se crean en el momento en que pueden ser necesarias: cuando se va a crear el primer objeto de la clase, en cuanto se llama a un mtodo static o en cuanto se utiliza una variable static de dicha clase. Lo importante es que las variables miembro static se inicializan siempre antes que cualquier objeto de la clase.

Los mtodos static


Tambin llamados "de clase", pueden recibir objetos de su clase como argumentos explcitos, pero no tienen argumento implcito ni pueden utilizar la referencia this. Para llamar a estos mtodos se suele emplear el nombre de la clase, en vez del nombre de un objeto de la clase. Los mtodos y variables de clase son lo ms parecido que Java tiene a las funciones y variables globales de C/C++. Las restricciones que tiene un mtodo static son: 1. Solo pueden llamar otro mtodo static 2. Solo deben acceder a datos static 3. No se pueden referir a this o super de ninguna manera Si se necesita hacer algn tipo de computacin para inicializar las variables static, se puede declarar tambin un bloque static el cual se ejecutar solo una vez, cuando se carga.
class Estatica { static int a = 3; static int b; static void show(int x) { System.out.println("x = " + x); System.out.println("a = " + a); System.out.println("b = " + b); } static { System.out.println("Bloque esttico inicializado"); b = a * 4; //vemos que, aunque declarada como static //b se inicializa en tiempo de ejecucin }

Diario de un principiante (parte 4)

public static void main(String args[]) { show(15); } }

Tan pronto como Estatica se carga, todas las sentencias se ejecutan. Primero, a se inicializa a 3, luego se ejecuta el bloque esttico y, por ltimo, b se inicializa al valor asignado.

El operador final
Una variable que se declara como final, se previene que su contenido sea modificado. Esto significa que debes inicializar una variable como final cuando la declaras. No obstante, Java permite separar la definicin de la inicializacin. Esta ltima se puede hacer ms tarde, en tiempo de ejecucin, llamando a mtodos o en funcin de otros datos. La variable final as definida es constante pero no tiene porqu tener el mismo valor en todas las ejecuciones del programa, pues depende de cmo haya sido inicializada. Esto es lo ms parecido a las constantes de otros lenguajes de programacin. Por ejemplo:
final float PI = 3.1416;//Segn la convencin de cdigo las variables "constantes" //se ponen en maysculas. //Observa que ahora podrs usar esta variable sin miedo a //ser modificada, esto es, tienes una constante.

Aunque bsicamente este operador se emplea para crear constantes en Java, tambin podemos definir una clase o un mtodo como final. En el primer caso, no puede tener clases derivadas. Esto se hace por motivos de seguridad y de eficiencia, porque cuando el compilador sabe que los mtodos no van a ser redefinidos puede hacer optimizaciones adicionales. En el segundo, un mtodo declarado como final no puede ser redefinido por una clase que derive de su propia clase. En el prximo captulo acabaremos de ver otros conceptos de la POO y algunos aspectos del uso de clases con los operadores explicados. Tambin haremos un repaso de lo que son las clases internas y las clases anidadas. Leo Suarez est actualmente realizando el Proyecto Fin de Carrera en Java para obtener el ttulo de Ingeniero Superior de Telecomunicaciones por la Universidad de Las Palmas de Gran Canaria. Cuando no est proyectando o escribiendo para javaHispano aprovecha para disfrutar con la novia y los amigos del estupendo clima de esa maravillosa isla. Para cualquier duda o tirn de orejas, e-mail a: leo@javahispano.com

You might also like