Introducción a C#
Por Nacho Cabanes, versión 0.93 de 16-abr-2010


(Nota: Estás viendo una versión del curso antigua, creada en 2009. Es recomendable que sigas la versión 2015, mucho más actualizada, con contenidos más detallados, más ejemplos y más ejercicios propuestos)

6. Programación orientada a objetos

6.1. ¿Por qué los objetos?

Hasta ahora hemos estado "cuadriculando" todo para obtener algoritmos: tratábamos de convertir cualquier cosa en una función que pudiéramos emplear en nuestros programas. Cuando teníamos claros los pasos que había que dar, buscábamos las variables necesarias para dar esos pasos.

Pero no todo lo que nos rodea es tan fácil de cuadricular. Supongamos por ejemplo que tenemos que introducir datos sobre una puerta en nuestro programa. ¿Nos limitamos a programar los procedimientos AbrirPuerta y CerrarPuerta? Al menos, deberíamos ir a la zona de declaración de variables, y allí guardaríamos otras datos como su tamaño, color, etc.

No está mal, pero es "antinatural": una puerta es un conjunto: no podemos separar su color de su tamaño, o de la forma en que debemos abrirla o cerrarla. Sus características son tanto las físicas (lo que hasta ahora llamábamos variables) como sus comportamientos en distintas circunstancias (lo que para nosotros eran las funciones). Todo ello va unido, formando un "objeto".

Por otra parte, si tenemos que explicar a alguien lo que es el portón de un garaje, y ese alguien no lo ha visto nunca, pero conoce cómo es la puerta de su casa, le podemos decir "se parece a una puerta de una casa, pero es más grande para que quepan los coches, está hecha de metal en vez de madera...". Es decir, podemos describir unos objetos a partir de lo que conocemos de otros.

Finalmente, conviene recordar que "abrir" no se refiere sólo a una puerta. También podemos hablar de abrir una ventana o un libro, por ejemplo.

Con esto, hemos comentado casi sin saberlo las tres características más importantes de la Programación Orientada a Objetos (OOP):

Otro concepto importante es el de "clase": Una clase es un conjunto de objetos que tienen características comunes. Por ejemplo, tanto mi puerta como la de mi vecino son puertas, es decir, ambas son objetos que pertenecen a la clase "puerta". De igual modo, tanto un Ford Focus como un Honda Civic o un Toyota Corolla son objetos concretos que pertenecen a la clase "coche".

6.2. Objetos y clases en C#

Vamos con los detalles. Las clases en C# se definen de forma parecida a los registros (struct), sólo que ahora también incluirán funciones. Así, la clase "Puerta" que mencionábamos antes se podría declarar así:

public class Puerta
{
 
  int ancho;     // Ancho en centimetros
  int alto;      // Alto en centimetros
  int color;     // Color en formato RGB
  bool abierta;  // Abierta o cerrada
 
  public void Abrir() 
  {
    abierta = true;
  }
 
  public void Cerrar() 
  {
    abierta = false;
  }
 
  public void MostrarEstado() 
  {
    Console.WriteLine("Ancho: {0}", ancho);
    Console.WriteLine("Alto: {0}", alto);
    Console.WriteLine("Color: {0}", color);
    Console.WriteLine("Abierta: {0}", abierta);
  }
 
} // Final de la clase Puerta  

Como se puede observar, los objetos de la clase "Puerta" tendrán un ancho, un alto, un color, y un estado (abierta o no abierta), y además se podrán abrir o cerrar (y además, nos pueden "mostrar su estado, para comprobar que todo funciona correctamente).

Para declarar estos objetos que pertenecen a la clase "Puerta", usaremos la palabra "new", igual que hacíamos con los "arrays":

    Puerta p = new Puerta();
    p.Abrir();
    p.MostrarEstado();

Vamos a completar un programa de prueba que use un objeto de esta clase (una "Puerta"):

/*---------------------------*/
/*  Ejemplo en C# nº 59:     */
/*  ejemplo59.cs             */
/*                           */
/*  Primer ejemplo de clases */
/*                           */
/*  Introduccion a C#,       */
/*    Nacho Cabanes          */
/*---------------------------*/
 
using System;
 
public class Puerta
{
 
  int ancho;     // Ancho en centimetros
  int alto;      // Alto en centimetros
  int color;     // Color en formato RGB
  bool abierta;  // Abierta o cerrada
 
  public void Abrir() 
  {
    abierta = true;
  }
 
  public void Cerrar() 
  {
    abierta = false;
  }
 
  public void MostrarEstado() 
  {
    Console.WriteLine("Ancho: {0}", ancho);
    Console.WriteLine("Alto: {0}", alto);
    Console.WriteLine("Color: {0}", color);
    Console.WriteLine("Abierta: {0}", abierta);
  }
 
} // Final de la clase Puerta   
 
 
public class Ejemplo59
{
 
  public static void Main()
  {
    Puerta p = new Puerta();
 
    Console.WriteLine("Valores iniciales...");
    p.MostrarEstado();
 
    Console.WriteLine("\nVamos a abrir...");
    p.Abrir();
    p.MostrarEstado();
  }
 
}
 

Este fuente ya no contiene una única clase (class), como todos nuestros ejemplos anteriores, sino dos clases distintas:

El resultado de ese programa es el siguiente:

Valores iniciales...
Ancho: 0
Alto: 0
Color: 0
Abierta: False

Vamos a abrir...
Ancho: 0
Alto: 0
Color: 0
Abierta: True

Se puede ver que en C#, al contrario que en otros lenguajes, las variables que forman parte de una clase (los "atributos") tienen un valor inicial predefinido: 0 para los números, una cadena vacía para las cadenas de texto, o "False" para los datos booleanos.

Vemos también que se accede a los métodos y a los datos precediendo el nombre de cada uno por el nombre de la variable y por un punto, como hacíamos con los registros (struct). Aun así, en nuestro caso no podemos hacer directamente "p.abierta = true", por dos motivos:

También puede desconcertar que en "Main" aparezca la palabra "static", mientras que no lo hace en los métodos de la clase "Puerta". Veremos este detalle un poco más adelante.

Ejercicio propuesto :