Java para programadores. Métodos y variables static

EN JAVA, TODOS LOS MÉTODOS SE DEBEN DEFINIR dentro de una clase. Esto hace a Java tan especial en medio de los lenguajes de programación, ya que hay algunos que permiten que los métodos existan libremente. Uno de los propósitos de la clase, es poder agrupar juntos los métodos relacionados y las variables. Quizás los diseñadores de Java pensaron que todo debía estar relacionado con algo. Con esta filosófica motivación, los diseñadores de Java quisieron establecer un fuerte control acerca de cómo se podían llamar las cosas, dado que un programa Java, potencialmente tenia acceso a un numero enorme de métodos esparcidos por todo Internet. El hecho de agrupar estos métodos en clases ( y como veremos mas adelante, las clases en paquetes) ayuda a controlar la confusión resultante por tanto nombre distinto.

En Java un método puede ser static o non-static. Un método non-static se emplea en la programación orientada a objetos que veremos en el siguiente capítulo. Por el resto del capítulo, hablaremos únicamente de los métodos static. Un método static es una subrutina ordinaria que tiene la misma funcionalidad en Java que en cualquier otro lenguaje de programación no orientado a objetos.

 ——————————————————————————–

 La definición de un método en Java tiene la siguiente forma:

 modificadores tipo-retorno nombre-método ( lista-parámetros ) {
       instrucciones
}

Las instrucciones deben escribirse entre llaves, { y }, están dentro de la “caja negra”, que hemos explicado en la sección anterior. Son las instrucciones que el ordenador ejecuta cuando se llama al método. La subrutinas pueden contener cualquiera de las instrucciones presentadas anteriormente. Ya hemos visto bastantes ejemplos de métodos, llamados main() en los programas ejemplo que hemos visto hasta ahora. Aquí tenemos algunos ejemplos con la parte “interna” omitida (pero recuerde que semejantes definiciones, solo pueden aparecer dentro de las clases):

 

static void playGame() {
// “static” es el modificador; “void” es tipo-retorno;
           // “playGame” es el nombre; la lista de parámetros
          // esta vacía
          . . .
// las instrucciones para definir el método van aquí

}

int getNextN(int N) {
// no hay modificadores; “int” es el tipo retorno
// “getnextN” es el nombre del método;
         // la lista de parámetros incluye uno
        // llamado “N” y con tipo “int”
        . . .
// instrucciones para definir el método

}

 

public static boolean lessThan(double x, double y) {
// “public” y “static” son modificadores;
// “boolean” es el tipo a retornar;
// “lessThan” es el nombre del método;
// la lista de parámetros incluye dos con
// nombres “x” e “y”, el tipo de cada parámetro
// es “double”
. . .
// instrucciones para implementar el método
}

Los modificadores son palabras que definen ciertas características del método, como si es static o no.

En el segundo ejemplo que presentamos, getNextN es un método non-static dado que en su definición no incluye el modificador “static” — y esto no es un ejemplo de lo que vamos a ver en este capítulo!.

El otro modificador que presentamos en este ejemplo, es “public”. Este modificador indica que el método puede ser llamado desde cualquier lugar del programa e incluso desde fuera de la clase en donde se ha definido.

Otro modificador “private” indica que el método puede ser llamado únicamente desde dentro de la clase.

Los modificadores public y private se llaman limitadores de acceso (access specifiers). ( Si en un método no se definen limitadores de acceso, por defecto este método puede ser llamado por cualquiera dentro del “package” que contiene a la clase –Veremos mas sobre “packages” en la Sección 5.) Hay algunos otros modificadores que iremos viendo a lo largo del curso.

De alguna manera, puede sentirse extrañado de que existan los limitadores de acceso.

Porqué no se permite que todo sea público?.

Bien, piense que la misma clase, es una especie de caja negra. Los métodos públicos son parte de la interface de la caja negra, mientras que los métodos privados son parte de la implementacion oculta de la caja.

Las reglas de las cajas negras implican que solo se debe declarar un método como publico si es realmente una parte importante de la interface que se ve desde fuera de la caja. Quiere verlo realmente?.

Algunas subrutinas están diseñadas para calcular y devolver valores. Estas subrutinas, se llaman funciones.

Hemos visto ejemplos de funciones matemáticas como Math.sqrt(x) y Math.random() en la Sección 2.6.

Si escribe un método que va a ser usado como función, deberá especificar el tipo de retorno del método, que será el tipo de valor que se calcula con la función.

Por ejemplo el tipo de retorno boleano en

public static boolean lessThan(double x, double y)

indica que la función lessThan calcula un valor boleano. Estudiaremos mas las funciones en la Sección 4

Un método también puede ser usado como una subrutina normal; para indicarle que no devuelve ningún valor, deberemos especificar como tipo de retorno “void”. Este termino se emplea para indicar que no existe valor de retorno o que este esta vacío.

Finalmente viene la lista de parámetros del método. Los parámetros forman parte de la interface del método, representan la información que se pasa al metodo desde el exterior, para que sean usados  en sus cálculos internos.

Para un ejemplo concreto, imaginemos una clase llamada Televisión que incluye el método llamado changeChanel(). La pregunta inmediata es :

A que canal queremos cambiar?.

El parámetro se puede utilizar para resolver esta cuestión; dado que el numero de canal es un entero, el tipo del parámetro debería ser int y la declaración del método changeChanel() podría ser así:

 public void changeChannel(int channelNum) {…}

Esta declaración indica que changeChanel()tiene un parámetro de tipo int. Cuando se llama al método se le debe proporcionar un numero de canal; por ejemplo changeChanel(127);

Los parámetros los trataremos en detalle en la siguiente sección.

 ——————————————————————————–

 Cuando define un método, deberá decirle al ordenador que el método existe, y que  quiere utilizarlo. Los métodos no se ejecutan hasta que son llamados. (Esto es cierto excepto para el método MAIN()–aun cuando no se le llame, cuando el sistema arranca el programa, lo llama directamente).

Por ejemplo el método playGame() definido anteriormente, puede ser llamado utilizando la siguiente instrucción desde dentro de la clase:

 playGame();

Esta instrucción puede aparecer en cualquier sitio de la misma clase que incluye la definición de playGame(), desde el método main() o desde cualquier otro método. Dado que playGame() en un método público, también puede ser llamado desde otras clases, pero en ese caso, le deberá indicar al ordenador que clase lo contiene.

Supongamos por ejemplo que playGame() esta definido en una clase llamada Poker. Entonces para efectuar la llamada desde fuera de la clase, debería escribir:

 Poker.playGame();

Para usar el nombre de clase, aquí debe decirle al ordenador en que clase debe buscar para encontrar el método. Eso también le permite distinguir entre Poker.playGame() y otro posible método playGame() definido en otra clase como Roulette.playGame() o Blackjack.playGame().

De forma general, la instrucción de llamada a un método tiene la forma:

 nombre-método(parámetros);

si el método esta definido en la misma clase o

 nombre-clase.nombre-método(parámetros);

si el método es static definido en cualquier parte , en diferente clase, (Los Non-static definido en otras clases tienen un comportamiento ligeramente distinto, como veremos mas adelante)

 ——————————————————————————–

 Es el momento de presentar como ejemplo un programa completo para que pueda ver como incluye otros métodos además del método main. Aquí esta el programa para poder jugar con el usuario a adivinar números — excepto que he omitido el interior del método playGame()

 

public class GuessingGame {

            public static void main(String[] args) {
               Console console = new Console();

               console.putln("Quiero jugar.  Pensaré un número entre");
               console.putln("1 y 100, y pruebe a ver si lo adivina.");

               boolean playAgain;

               do {
                  playGame();  // llama a la subrutina para jugar
                  console.put("Quiere jugar otra vez? ");
                  playAgain = console.getlnBoolean();
               } while (playAgain);

               console.close();
            } // end of main()

            static void playGame() {
               . . .  // instrucciones de implementacion del juego
            } // end of playGame()

         } // end of class GuessingGame

Esto es el boceto del posible programa para jugar, pero tan pronto como acabé la definición de playGame, me encontré con un problema!:

El problema es que necesito hacerle preguntas al usuario y leer sus respuestas, y por lo tanto, necesito usar la consola.

Sin embargo la console es una variable local definida dentro del método main(). Las reglas dicen que una variable definida localmente, dentro de un método, es parte de la caja negra, y es completamente inaccesible desde fuera. Así no hay forma de que pueda usar la consola desde dentro de playGame()! ( En caso de que se extrañe, si estoy definiendo en playGame() una variable Console será completamente distinta a la console definida en main() — y serán dos ventanas distintas en la pantalla!).

Hay una solución sencilla: En lugar de inicializar en el método una variable local, console puede ser una variable static perteneciente a la clase GuessingGame.

La variable puede ser declarada en la clase fuera de cualquier método.Esas variables pueden ser indistintamente static o non-static, pero este método, lo utilizaremos en este capítulo para las static.

Los miembros variables, pueden ser declarados indistintamente public o private. Un miembro variable static puede ser utilizado en cualquier metodo definido en la misma clase. Y si es publico puede ser accedido desde fuera de la clase utilizando el nombre compuesto con la forma:

 class-name.variable-name

Mientras que en un método, una variable local solo existe mientras el bloque se ejecuta, una variable static existe mientras el programa este funcionando.

Por mover la declaración de console fuera del método main() la transformamos en variable static y que puede ser accedida por cualquiera de las dos rutinas, main(), y playGame(). Aquí esta el programa ejemplo completo:

Nota: Para poder probar esta clase, necesita descargar las clases “Console.java” y “ConsoleCanvas.java” y dejarlo en la misma carpeta donde va a escribir el fuente

package curso;

import ConsolaIO.Console;

public class GuessingGame {

    static Console console;  // declara console como static variable

    public static void main(String[] args) {
       console = new Console(); 

       console.putln("Quiero jugar.  Pensare un número entre");
       console.putln("1 y 100, y pruebe a ver si lo adivina.");

       boolean playAgain;

       do {
          playGame();  // call subroutine to play one game
          console.put("Quiere jugar otra vez? ");
          playAgain = console.getlnBoolean();
       } while (playAgain);

       console.close();
    } // end of main()

    static void playGame() {

    int computersNumber = (int)(100 * Math.random()) + 1;
      // El valor asignado a computerNumber es aleatorio
      // y escogido entre 1 y 100, inclusive
        int usersGuess; // aquí se guarda el numero pensado por el usuario
    console.putln();
    console.put("Cual es su primera jugada? ");
    do {
        usersGuess = console.getInt();
        if (usersGuess == computersNumber)
         console.putln("Lo consiguió!  Mi numero era " + computersNumber);
        else if (usersGuess  computersNumber)
          console.put("Es muy alto, vuelva a probar: ");
    } while (usersGuess != computersNumber);
    console.putln();
        } // end of playGame()

 } // end of class GuessingGame

Tómese algo de tiempo para leer el programa cuidadosamente e intente adivinar como funciona. Y pruebe de convencerse usted mismo utilizando un caso relativamente simple, separe el programa en dos métodos para que le sea mas fácil entenderlo y probablemente logrará que le sea fácil el escribir cada parte.

Puede probar la salida con el programa de simulación aquí:

[htmlbox file=GuessingGame.html]

Acerca de Miguel Garcia

Programador, Desarrollador web, Formador en distintas areas de informatica y director de equipos multidisciplinares.
Esta entrada fue publicada en Formacion, Java y etiquetada , . Guarda el enlace permanente.

Deja un comentario