## Constructores

Todas las clases Java tienen métodos especiales llamados Constructores que se utilizan para inicializar un objeto nuevo de ese tipo. Los contructores tienen el mismo nombre que la clase --el nombre del constructor de la clase Rectangle es Rectangle(), el nombre del constructor de la clase Thread es Thread(), etc...

Java soporta la sobrecarga de los nombres de métodos para que una clase puede tener cualquier número de constructores, todos los cuales tienen el mismo nombre. Al igual que otros métodos sobrecargados, los constructores se diferencian unos de otros en el número y tipo de sus argumentos.

Consideremos la clase Rectangle del paquete java.awt que proporciona varios constructores diferentes, todos llamados Rectangle(), pero cada uno con número o tipo diferentes de argumentos a partir de los cuales se puede crear un nuevo objeto Rectangle. Aquí tiene las firmas de los constructores de la clase java.awt.Rectangle:

    public Rectangle()
    public Rectangle(int width, int height)
    public Rectangle(int x, int y, int width, int height)
    public Rectangle(Dimension size)
    public Rectangle(Point location)
    public Rectangle(Point location, Dimension size)

El primer constructor de Rectangle inicializa un nuevo Rectangle con algunos valores por defecto razonables, el segundo constructor inicializa el nuevo Rectangle con la altura y anchura especificadas, el tercer constructor inicializa el nuevo Rectangle en la posición especificada y con la altura y anchura especificadas, etc...

Típicamente, un constructor utiliza sus argumentos para inicializar el estado del nuevo objeto. Entonces, cuando se crea un objeto, se debe elegir el constructor cuyos argumentos reflejen mejor cómo se quiere inicializar el objeto.

Basándose en el número y tipos de los argumentos que se pasan al constructor, el compilador determina cual de ellos utilizar, Así el compilador sabe que cuando se escribe:

    new Rectangle(0, 0, 100, 200);

el compilador utilizará el constructor que requiere cuatro argumentos enteros, y cuando se escribe:

    new Rectangle(miObjetoPoint, miObjetoDimension);

utilizará el constructor que requiere como argumentos un objeto Point y un objeto Dimension.

Cuando escribas tus propias clases, no tienes porque proporcionar constructores. El constructor por defecto, el constructor que no necesita argumentos, lo proporciona automáticamente el sistema para todas las clases. Sin embargo, frecuentemente se querrá o necesitará proporcionar constructores para las clases.

Se puede declarar e implementar un constructor como se haría con cualquier otro método en una clase. El nombre del constructor debe ser el mismo que el nombre de la clase y, si se proporciona más de un constructor, los argumentos de cada uno de los constructores deben diferenciarse en el número o tipo. No se tiene que especificar el valor de retorno del constructor.

El constructor para esta subclase de Thread, un hilo que realiza animación, selecciona algunos valores por defecto como la velocidad de cuadro, el número de imágenes y carga las propias imágenes:

    class AnimationThread extends Thread {
        int framesPerSecond;
        int numImages;
        Image[] images;

        AnimationThread(int fps, int num) {
            int i;

            super("AnimationThread");
            this.framesPerSecond = fps;
            this.numImages = num;

            this.images = new Image[numImages];
            for (i = 0; i <= numImages; i++) {
                . . .
                // Carga las imágenes
                . . .
            }
        }
    }

Observa cómo el cuerpo de un constructor es igual que el cuerpo de cualquier otro método -- contiene declaraciones de variables locales, bucles, y otras sentencias. Sin embargo, hay una línea en el constructor de AnimationThread que no se verá en un método normal--la segunda línea:

    super("AnimationThread");

Esta línea invoca al constructor proporcionado por la superclase de AnimationThread--Thread. Este constructor particular de Thread acepta una cadena que contiene el nombre del Thread. Frecuentemente un constructor se aprovechará del código de inicialziación escrito para la superclase de la clase.

En realidad, algunas clases deben llamar al constructor de su superclase para que el objeto trabaje de forma apropiada. Tipicamente, llamar al constructor de la superclase es lo primero que se hace en el constructor de la subclase: un objeto debe realizar primero la inicialización de nivel superior.

Cuando se declaren constructores para las clases, se pueden utilizar los especificadores de acceso normales para especificar si otros objetos pueden crear ejemplares de sus clase:

private
  Niguna otra clase puede crear un objeto de su clase. La clase puede contener métodos públicos y esos métodos pueden construir un objeto y devolverlo, pero nada más.
protected
  Sólo las subclases de la clase pueden crear ejemplares de ella.
public
  Cualquiera pueda crear un ejemplar de la clase.
package-access
  Nadie externo al paquete puede construir un ejemplar de su clase. Esto es muy útil si se quiere que las clase que tenemos en un paquete puedan crear ejemplares de la clase pero no se quiere que lo haga nadie más.

Ozito