Declaración de Clases en Java

Bueno vamos hoy con otra entrada de Java, la cual se basa en la declaración de las clases. Veremos como se desarrolla el código que declare clases (incluyendo clases abstractas y todas las formas de anidar clases), interfaces, enumeraciones y incluir el uso apropiado de las sentencias package e import (incluyendo static imports).


Para empezar veremos el uso adecuado de las sentencias import y package, ya que en cualquier archivo fuente de java que encontremos, es lo primero que veremos y debemos hacer un uso adecuado de ellas.

Reglas de declaración en archivos fuente

  • Solo una clase public puede ser declarada por archivo de código fuente.

  • Los comentarios pueden aparecer en cualquier lugar.

  • Si hay una clase public en un archivo, el nombre del archivo debe ser como el nombre de la clase.

  • Si la clase pertenece a un paquete, la sentencia de package debe estar en la primera línea del código fuente

  • Si hay alguna sentencia import, esta debe ir entre la sentencia package y la declaración de la clase. Si no hay sentencia package, el import será lo primero.

  • import y package se aplican a todas las clases dentro de un archivo de código fuente.

  • Un archivo puede tener mas de una clase que no sea pública

  • Archivos con ninguna clase pública pueden tener un nombre que no coincida con las clases que hay en el fichero

Declaración de Clases y Modificadores

Para declarar una clase se hace de la siguiente manera:

class MyClass{}

Este código compilaría bien, pero podemos añadir tambien modificadores antes de la declaración de la clase. Los modificadores pueden dividirse en dos categorías:

  • Modificadores de acceso
    • public
    • protected
    • private
  • Modificadores de no-acceso
    • strictfp
    • final
    • abstract

  • Acceso de Clases

    ¿Que significa acceder a una clase? Cuando decimos que el código de una clase (class A) tiene acceso a otra clase (class B), significa que la clase A puede hacer una de estas tres cosas.

    • Crear una instancia de la clase B.
    • Heredar de la clase B (En otras palabras, convertirse en una subclase de la clase B).
    • Acceder a ciertos métodos y variables dentro de la clase B, dependiendo del control de acceso de estos métodos y variables

    En efecto, acceso significa visibilidad. Si la clase A no puede ver a la clase B, el nivel de acceso de los métodos y variables dentro de la clase B no importan, la clase A no tiene ningún camino de acceso a estos métodos y variables.

  • Acceso por defecto

    Una clase con un acceso por defecto no tiene modificador que preceda a la declaración de la clase, es el tipo de control de acceso que obtenemos cuando no ponemos ningún modificador en la declaración de la clase. Pensemos en el acceso por defecto del nivel de acceso de paquete, porque una clase con el acceso por defecto puede ser solo vista por las clases dentro del mismo paquete. Por ejemplo , si la clase A y la clase B estan en diferentes paquetes, y la clase A tiene acceso por defecto, la clase B no podrá crear una instancia de la clase A, o declarar una variable o retornar una del tipo de la clase A.

  • Acceso publico

    La declaración de una clase con public le da a todas las clases de todos los paquetes a tener acceso a la clase definida como public. En otras palabras, todas las clases del universo de Java tiene acceso a esta clase pública. No olvidemos, que si una clase pública que estas intentando usar está en un paquete diferente de una clase que estas escribiendo, necesitarás tambíen que importar la clase pública.

  • Otros (No de aceso) Modificadores de clase

    Podemos modificar la declaración de una clase usando la palabra final, abstract o strictfp. Estos modificadores están en adición a cualquier otro control de acceso que tenga la clase, por lo que podríamos, por ejemplo, declarar una clase como public y final, pero no podemos mezclar modificadores que no sean de acceso.

    Somos libres de usar strictfp en combinación con final, pero nunca debemos, nunca, marcar una clase como final y abstract. Veremos las causas en las siguientes 2 secciones.

    No necesitamos saber como funciona strictfp, solo que se enfoca en modificar una clase o un método, pero nunca una variable.

  • Clases Finales

    Cuando se usa en la declaración d euna clase, la palabra final, significa que la clase no puede generar subclases. En otras palabras, ninguna otra clase puede nunca extender a esta o heredar de ella, y cualquier intento de ello nos dará un error de compilación.

    Por tanto, ¿Por qué marcar una clase como final?, al fin y al cabo podríamos decir que está violando la noción de herencia de la orientación a objetos (OO). Deberíamos hacer una clase final solo si necesitaramos una absoluta garantía de que ninguno de los métodos en esa clase van a ser nunca sustituídos. Veremos que muchas clases en las librerías del núcleo de Java son final, como por ejemplo la clase String.

    			public final class Beverage {
        			public void importantMethod(){
            			System.out.println("Prueba");
        			}
    			}
    			

    			public class Tea extends Beverage{
        
    			}
    			

    La segunda clase, Tea, intenta heredar de la clase Beverage que tiene un modificador final, por lo que dá error ya que estamos intentando que se herede de una clase final.

  • Clase Abstracta

    Una clase abstracta no puede ser instanciada. Su único propósito, su misión en la vida, raison d’être, es ser extendida. (Podemos compilar y ejecutar una clase abstracta, tanto tiempo como queramos hasta que intentemos hacer una instancia de ella).

    ¿Por qué crear una clase si no podemos hacer objetos de ellas? Porque la clase es eso, abstracta. Imaginemos que tenemos una clase Car que tiene métodos genéricos y comunes a todos los vehículos, pero no queremos que nadie cree un objeto genérico y acbstracto Car. ¿Como inicializarían sus estados? ¿Qué color tendrían? =Cuantos asientos? En otras palabras, ¿Como se implementarían estos métodos?.

    Necesitamos programadores que instancien tipos de coches actuales como BMWBoxster y SubaruOutback. Si preguntamos al propietario de un Boxster nos dirá que el suyo hace cosas que un Subaru no “haría ni en sueños”. Veamos pues la siguiente clase abstracta:

    			public abstract class Car {
    			    private double price;
    			    private String model;
    			    private String year;
    			    public abstract void goFast();
    			    public abstract void goUpHill();
    			    public abstract void impressNeighbors();
    			        //El código adicional, importante y serio viene aquí
    			}
    			

    El código anterior compilará bien, sin embargo, si intentas instanciar un Car obtendremos un error de compilación debido a que es una clase abstracta.

    Si el método en una clase abstracta termina con ; entonces el método y la clase deben ser marcados como abstract. Si vemos una pregunta en la que tenemos que arreglar un código que incluye un método terminado en ; pero sin el modificador abstract en la clase o en el método. En este caso, podríamos marcar el método y la clase como abstract o cambiar el ; por código (como {…}). Si un método en la clase es abstracta, entonces la clase debe ser abstracta, aunque podemos tener métodos que no sean abstractos, en el ejemplo de antes podría existir algo que no se diferencia de un tipo de coche a otro.

Hasta aquí el asunto de la declaración de clases por si teníamos alguna duda sobre las clases públicas, finales, abstractas.

Cualquier aporte o corrección es bienvenido.

Saludos!!!