Ahora que ya sabemos cómo definir
las clases de objetos que podremos usar en nuestras aplicaciones ha llegado el
momento de explicar cómo crear objetos de una determinada clase. Algo de ello
ya se introdujo en el Tema 4: Aspectos
Léxicos cuando se comentó la utilidad del operador new, que precisamente es crear objetos y cuya sintaxis es:
new <nombreTipo>(<parametros>)
Este operador crea un nuevo
objeto del tipo cuyo nombre se le indica y llama durante su proceso de creación
al constructor del mismo apropiado según los valores que se le pasen en <parametros>, devolviendo una referencia al
objeto recién creado. Hay que resaltar el hecho de que new no
devuelve el propio objeto creado, sino una referencia a la dirección de memoria
dinámica donde en realidad se ha creado.
El antes comentado constructor de un objeto no es más que
un método definido en la definición de su tipo que tiene el mismo nombre que la
clase a la que pertenece el objeto y no tiene valor de retorno. Como new siempre
devuelve una referencia a la dirección de memoria donde se cree el
objeto y los constructores sólo pueden usarse como operandos de new,
no tiene sentido que un constructor devuelva objetos, por lo que no tiene
sentido incluir en su definición un campo <tipoDevuelto>
y el compilador considera erróneo hacerlo (aunque se indique void)
El constructor recibe ese nombre
debido a que su código suele usarse precisamente para construir el objeto, para
inicializar sus miembros. Por ejemplo, a nuestra clase de ejemplo Persona le podríamos añadir un constructor dejándola así:
class
Persona
{
string Nombre; // Campo de cada objeto Persona que almacena su nombre
int Edad; // Campo de cada objeto Persona que almacena
su edad
string NIF; // Campo de cada objeto Persona que almacena
su NIF
void Cumpleaños() // Incrementa en uno la edad del objeto Persona
{
Edad++;
}
Persona (string nombre, int edad, string
nif) // Constructor
{
Nombre
= nombre;
Edad
= edad;
NIF
= nif;
}
}
Como se ve en el código, el
constructor toma como parámetros los valores con los que deseemos inicializar
el objeto a crear. Gracias a él, podemos crear un objeto Persona de nombre José, de 22 años de edad y NIF
12344321-A así:
new
Persona(“José”, 22, “12344321-A”)
Nótese que la forma en que se
pasan parámetros al constructor consiste en indicar los valores que se ha de
dar a cada uno de los parámetros indicados en la definición del mismo separándolos
por comas. Obviamente, si un parámetro se definió como de tipo string habrá que pasarle una cadena, si se definió de
tipo int habrá que pasarle un entero y, en general, ha
todo parámetro habrá que pasarle un valor de su mismo tipo (o de alguno convertible
al mismo), produciéndose un error al compilar si no se hace así.
En realidad un objeto puede tener
múltiples constructores, aunque para diferenciar a unos de otros es obligatorio
que se diferencien en el número u orden de los parámetros que aceptan, ya que
el nombre de todos ellos ha de coincidir con el nombre de la clase de la que
son miembros. De ese modo, cuando creemos el objeto el compilador podrá
inteligentemente determinar cuál de los constructores ha de ejecutarse en
función de los valores que le pasemos al new.
Una vez creado un objeto lo más
normal es almacenar la dirección devuelta por new en una
variable del tipo apropiado para el objeto creado. El siguiente ejemplo -que
como es lógico irá dentro de la definición de algún método- muestra cómo crear
una variable de tipo Persona llamada
p y cómo almacenar en ella la
dirección del objeto que devolvería la anterior aplicación del operador new:
Persona p; // Creamos variable p
p = new
Persona(“Jose”, 22, “12344321-A”); //
Almacenamos en p el objeto creado con new
A partir de este momento la
variable p contendrá una referencia
a un objeto de clase Persona que
representará a una persona llamada José de 22 años y NIF 12344321-A. O lo que
prácticamente es lo mismo y suele ser la forma comúnmente usada para decirlo:
la variable p representa a una persona
llamada José de 22 años y NIF 12344321-A.
Como lo más normal suele ser
crear variables donde almacenar referencias a objetos que creemos, las
instrucciones anteriores pueden compactarse en una sola así:
Persona
p = new Persona(“José”, 22, “12344321-A”);
De hecho, una sintaxis más
general para la definición de variables es la siguiente:
<tipoDato>
<nombreVariable> = <valorInicial>;
La parte =
<valorInicial> de esta sintaxis es en realidad opcional, y si no
se incluye la variable declarada pasará a almacenar una referencia nula
(contendrá el literal null)