RSS

Orientación a Objetos (VII) – Miembros estáticos

10 Jun

Static

La palabra clave static declara miembros (atributos, métodos y clases anidadas) que están asociados a la clase en lugar de a una instancia de la clase.

Utilidad

A veces puede ser útil tener una variable compartida por todos los objetos de la clase (algo parecido a una variable global). En este caso marcaríamos esta variable como static.

Si una variable static no se marca como private, es posible acceder a ella desde fuera de la clase. Para hacerlo, no se necesita ningún objeto, se hace referencia a ella mediante el nombre de la clase.

Por ejemplo, un caso común es un contador de los objetos instanciados de una clase:

public class Leccion{
    public static int contador; //variable estática, asociada a la clase
    private int idLeccion;      //atributos, variables no estáticas
    private String desLeccion; //asociadas a los objetos

    public Leccion()
    {
        contador = contador + 1;  //podemos usar el contador para el id de cada objeto Leccion.
        idLeccion = contador;
        desLeccion = "Sin nombre";
    }
}

 

public class MainLeccion{
    public static void main (String[] args){
        System.out.println("Contador: " + Leccion.contador); //Muestra 0
        Leccion l1 = new Leccion();
        Leccion l2 = new Leccion();
        System.out.println("Contador: " + Leccion.contador); //Muestra 2
    }

}

O cuando necesitemos un método cuyo código no dependa de los atributos de un objeto de la clase. En este caso marcaríamos este método como static.

Por ejemplo, podríamos hacer la variable estática anterior privada y obtener el número de objetos Leccion creados mediante un método getContador().

public class Leccion{
    private static int contador; //variable estática, asociada a la clase
    public static int getContador(){ //método estático
         return contador;
    }

    private int idLeccion;     //atributos, variables no estáticas
    private String desLeccion; //asociadas a los objetos

    public Leccion()
    {
        contador = contador + 1;  //podemos usar el contador para el id de cada objeto Leccion.
        idLeccion = contador;
        desLeccion = "Sin nombre";
    }
}

En la clase principal ahora llamaríamos al método estático:

public class MainLeccion{
    public static void main (String[] args){
        System.out.println("Contador: " + Leccion.getContador()); //Muestra 0
        Leccion l1 = new Leccion();
        Leccion l2 = new Leccion();
        System.out.println("Contador: " + Leccion.getContador()); //Muestra 2
    }


Accediendo a Miembros Estáticos

Anteriormente hemos visto que para acceder a las variables y métodos estáticos hemos utilizado el nombre de la clase y el operador punto. Es lo más lógico dado que las variables y métodos estáticos pertenecen a la clase, pero Java permite también acceder a los miembros estáticos utilizando un objeto.

Java lo permite pero el compilador realmente lo sustituirá por el nombre de la clase.

En el ejemplo anterior podíamos haber escrito:

 System.out.println("Contador: " + l2.getContador());

Esto último solo lo podremos hacer si existe una instancia de la clase.

Redefinición en Métodos Estáticos

Los métodos estáticos no se pueden sobrescribir (override), sin embargo si es posible tener el mismo método en una subclase. Esto se denomina redefinición o ocultación.

Si se llama al método con una referencia de objeto, el método llamado será el correspondiente a la clase para la que se haya declarado la variable.

¿Qué diferencia existe entre la sobrescritura y la redefinición?

La sobrescritura (override) está íntimamente ligada al polimorfismo. Como los métodos estáticos están asociados a la clase en lugar de a los objetos, el polimorfismo en tiempo de ejecución no es posible y por lo tanto no es sobrescritura sino redefinición.

Veamos la diferencia. Creamos una clase Persona y una subclase Cliente. Creamos un método no estático, mostrar() y un método estático, mostrarStatic() en cada una de las clases.

public class Persona{
    private String nif;
    private String nombre;
    private int edad;

    public Persona(String nif, String nombre, int edad){
        this.nif = nif;
        this.nombre = nombre;
        this.edad = edad;
    }
    ... //getters, setters

    public void mostrar(){
        System.out.println("Persona " + nif + ":  \n Nombre: " + nombre + "\n Edad: " + edad);
    }
    public static void mostrarStatic(){
        System.out.println("Clase Persona");
    }
}

 

public class Cliente extends Persona{
    private int id;
    private int antiguedad;
    private int descuento;

    public Cliente(String nif, String nombre, int edad, int id, int antiguedad, int descuento) {
        super(nif, nombre, edad);
        this.id = id;
        this.antiguedad = antiguedad;
        this.descuento = descuento;
    }
    ... // getters, setters

    public void mostrar(){
        System.out.println("Cliente" + id + ":  \n Nombre: " + getNombre()
         + "\n Antigüedad: " + antiguedad + "\n Descuento: " + descuento);
    }
    public static void mostrarStatic(){
        System.out.println("Clase Cliente");
    }
}

Con esta definición de clases si creamos los siguientes objetos tendríamos los siguientes resultados:

  public class MainSobrescritura{
      public static void main(String[] args){
          Persona per = new Persona("18520147L", "Maria Victoria Rodriguez", 18);
          Cliente cli = new Cliente("20415789M", "Secundino Jimenez", 25, 504, 5, 1);
          Persona per2 = new Cliente("41605788R", "Luis Martin", 30, 905, 3, 2);

          per.mostrar(); //llama a mostrar() de Persona
          cli.mostrar(); //llama a mostrar() de Cliente
          per2.mostrar();//llama a mostrar() de Cliente
      }
  }

Ahora veamos lo que ocurre con un método estático:

public class MainRedefinicion{
    public static void main(String[] args){
       Persona per = new Persona("18520147L", "Maria Victoria Rodriguez", 18);
       Cliente cli = new Cliente("20415789M", "Secundino Jimenez", 25, 504, 5, 1);
       Persona per2 = new Cliente("41605788R", "Luis Martin", 30, 905, 3, 2);

        per.mostrarStatic(); //llama a mostrarStatic de Persona
        cli.mostrarStatic(); //llama a mostrarStatic de Cliente
        per2.mostrarStatic();//llama a mostrarStatic de Persona y no de Cliente como arriba.
    }
}

Vemos que en los métodos estáticos el método llamado será el de la clase declarada en tiempo de compilación y no en tiempo de ejecución como pasa con los métodos no estáticos sobrescritos.

Acceso en un método estático

Un método estático no puede acceder a ninguna variable salvo a las variables locales, los atributos static y sus parámetros. Cualquier intento de acceder a atributos que no sean estáticos directamente (sin crear un objeto) provoca un error de compilación.

Nota

El método main es también un método estático. Podemos comprobar que no creamos ningún objeto para ejecutarlo.Si necesita datos miembro se deben crear objetos dentro de main.

Anuncios
 
1 comentario

Publicado por en 10 junio, 2011 en Estudio, Tema 2

 

Etiquetas: , , , , ,

Una respuesta a “Orientación a Objetos (VII) – Miembros estáticos

  1. kevin murillo varela

    9 julio, 2015 at 2:41 pm

    gracias , un saludo desde colombia

     

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: