sábado, 5 de octubre de 2013

Constructores de Instancia en C#

Tabla de Contenido

0. Introducción
1. Constructores
2. Sobrecarga de Constructores
3. Constructores Predeterminados
4. Orden de Inicialización de Campos y Constructores de Instancia
5. Constructores non-public
6. Conclusiones
7. Glosario
8. Referencias

0. Introducción

Pasemos a descubrir otro de los miembros de una clase: los constructores de instancia. Los constructores perfilan el estado inicial cuando se crea una instancia u objeto de una clase. Recorreremos temas relacionados como: sobrecarga de constructores (muy similar como ocurre con los métodos), detalles de los constructores por defecto, el orden de inicialización de campos de instancia, en qué consiste los constructores no públicos y su utilidad, y la importancia de los constructores en el proceso de herencia.

1. Constructores

Los constructores son métodos especiales encargados de la inicialización del estado de una instancia u objeto a crear. Veremos que existe una diferencia sutil entre un método y un constructor: éste último en su definición no se especifica un valor de retorno (ni siquiera void).

Este es un ejemplo que demuestra el concepto anterior:

Archivo C# Usuario.cs [enlace alternativo]:
En las líneas 5-8 se define el constructor para Usuario. En el cuerpo del constructor se especifica la sentencia de inicialización para el campo de instancia namename = n;.

Invocación del Constructor de Instancia

En la siguiente línea de código fuente C#:

Usuario objUsuario = new Usuario ("Valentina"); // Llamada al constructor

Observemos que después del operador new se especifica el constructor que definimos en la línea 5 de la clase Usuario. Luego se pasa como argumento, en este caso particular, el nombre del usuario como una cadena de caracteres string.

Modificadores permitidos en la declaración de un constructor

  • Modificadores de acceso:
    • public
    • internal
    • private
    • protected
  • Modificadores de código no administrado:
    • unsafe (más acerca de este modificador en [1])
    • extern
En este otro ejemplo (obtenido desde [2]):

Archivo C# Visibilidad.cs [enlace alternativo]:
Estas son las firmas de los constructores declarados en la clase Coordenada:
  • Coordenada()
  • Coordenada(int x, int y)
[Nota: En el tema 2 veremos la sobrecarga de constructores]. Lo que aquí quiero resaltar es la forma en que podemos inicializar una instancia. En la primera versión asignamos valores por defecto para la abscica (x) y la ordenada (y): el valor es cero (0) para ambas.

Por otro lado, la segunda versión declara dos parámetros para inicializar las coordenadas. Esto se logra a través las instrucciones:

this.x = x;
this.y = y;

Obsérve el uso de this [3]. Este operador permite hacer referencia a la instancia actual. this.x = x; significa que estamos asignando el valor del argumento x al campo de instancia x (this.x). Además, estamos evitando el conflicto entre variables locales y de campos de instancia.

2. Sobrecarga de Constructores

La sobrecarga de un constructor consiste en definir diferentes maneras de inicializar un objeto de una clase en el momento crearlo. El cuerpo del constructor, esencialmente, está compuesto por código de inicialización de los miembros del tipo, en particular, los campos (dado que estos representan el estado del objeto).


Se tiene una clase Impresora con tres constructores sobrecargados:
  • Impresora()
  • Impresora (string marca, string modelo)
  • Impresora (string marca, string modelo, bool multifuncional, int hpm) : this (marca, modelo)
La primera versión (constructor sin argumentos) lo único que hace es inicializar en false la variable multifuncional.

El segundo constructor tiene como parámetros marca y modelo. El código de inicialización asigna los valores a los campos de instancia.


En el tercer constructor ocurre algo especial: consiste en invocar el constructor con los argumentos modelo y marca. Esto es importante debido a que se evita la duplicación de código: invocando constructores para inicializar campos de determinada modo. Vale apuntar que primero se ejecuta el constructor que corresponda con la firma de la llamada que aparece después de la declaración: 

: this (marca, modelo)

En este caso, la segunda versión. Es posible que en el cuerpo de llamada a otro constructor, se utilice una expresión:

: this (marca, modelo.toString() )

Adicionalmente, en [5] aclaran:
The expression itself cannot make use of the this reference, for example, to call an instance method. (This is enforced because the object has not been initialized by the constructor at this stage, so any methods that you call on it are likely to fail.) It can however, call static fields.

3. Constructores Predeterminados

Cuando estemos creando un tipo de dato, y no especificamos ningún constructor de instancia, el compilador C# creará uno con las siguientes características:
  • Sin parámetros
  • Sin cuerpo de inicialización
  • Se asignará los valores por defecto a los campos de instancia [4]
  • Nivel de acceso public

4. Orden de Inicialización de Campos de Instancia y Constructor

En el artículo Campos en C# se aclaró que los campos de instancia en el momento de su declaración son inicializados con su valor por defecto. Esto es lo primero que ocurre antes de ejecutarse un constructor, en seguida, se ejecutaran cada una de las sentencias de inicialización en el orden establecido en el cuerpo del constructor.

5. Constructores non-public

Se refiere a aquellos constructores que no están disponibles para código cliente. Su uso está relacionado con la creación de objetos a través métodos estáticos.

En [5] se extienden con el siguiente fragmento:
A common reason to have a nonpublic constructor is to control instance creation via a static method call. The static method could be used to return an object from a pool rather than neccessarily creation a new object, or return various subclasses based on input arguments.
Además incluye el siguiente código fuente C# (con adaptaciones):

Archivo C# ConexionBaseDeDatos.cs [enlace alternativo]:

6. Herencia y Constructores

A través del siguiente código fuente C#:

Archivo C# Figura.cs [enlace alternativo]:
Y el diagrama de clases:
Relación de Herencia y Contructores
Figura 1. Relación de Herencia y Contructores.

Fijémonos que a medida que las clases especializadas heredan, por ejemplo, en la clase Circulo es posible invocar el constructor de la clase padre (o base) Figura como ocurre en la línea 21. De modo similar en la clase Circulo (la cual hereda de Circulo) se invoca el constructor que corresponde con la firma de: Circulo(double radio).

La anterior explicación nos da un vistazo sobre las poderosas funcionalidades del paradigma orientado a objetos en C#: reusamos código, evitamos ambigüedades en clases hijas.

7. Conclusiones

Los constructores son parte de los miembros de un tipo o estructura, y esto ha quedado demostrado en todo el pasaje anterior: hemos visto cómo declarar constructores, cómo sobrecargar un constructor (similar a un método), algunos modificadores que cambian el comportamiento y la visibilidad de los constructores, además, un vistazo general de cómo el lenguaje C# permite en la herencia invocar constructores de las clases padre (o base).

8. Glosario

  • base
  • Base
  • Constructor
  • Herencia
  • Sobrecarga
  • this

9. Referencias

[1]: unsafe (C# Reference) - http://msdn.microsoft.com/en-us/library/chfa2zb8.aspx
[2]: Instance Constructors (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/k6sa6h87.aspx
[3]: this (C# Reference) - http://msdn.microsoft.com/en-us/library/dk1507sz.aspx
[4]: Default Values Table (C# Reference) - http://msdn.microsoft.com/en-us/library/83fhsxwc.aspx
[5]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.

O

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.