Clases (Visual C# Express)
Actualización: noviembre 2007
C# es un lenguaje de programación orientado a objetos y, como otros lenguajes modernos, agrupa campos relacionados, métodos, propiedades y eventos en estructuras de datos denominadas clases.
Clases y objetos
Una clase es básicamente un plano para un tipo de datos personalizado. Cuando se define una clase, se utiliza cargándola en la memoria. Una clase que se ha cargado en la memoria se denomina objeto o instancia. Crea una instancia de una clase utilizando la palabra clave de C# new.
El siguiente es un ejemplo de definición de una clase denominada SampleClass y de creación de un objeto denominado sampleClass1 que es una instancia de esa clase. Como C# requiere que la función Main esté definida en una clase, el código siguiente también define una clase Program, pero esa clase no se utiliza para crear un objeto.
using System;
class SampleClass
{
public void SayHello()
{
Console.WriteLine("Hello, World!");
}
}
class Program
{
//Main is the entrypoint, where every C# program starts
static void Main(string[] args)
{
SampleClass sampleClass1 = new SampleClass(); // Create an object
sampleClass1.SayHello(); // Call a method
}
}
Al igual que se puede construir cualquier número de casas con un mismo plano, se pueden crear instancias de cualquier número de objetos con la misma clase. Es muy común tener matrices o listas que contienen muchos objetos de la misma clase. Cada instancia de la clase ocupa su propio espacio de memoria y los valores de sus campos (excepto los campos estáticos, como se describe a continuación) son independientes. En el ejemplo de código siguiente, puede crear un objeto de tipo Animal y establecer su tamaño en 2, y otro objeto cuyo tamaño puede establecer en 3. Sin embargo, hay una excepción importante a esta regla: el miembro estático.
Miembros estáticos y de instancia
Un miembro estático es un método o campo al que se puede obtener acceso sin hacer referencia a una instancia determinada de una clase. El método estático más común es Main, que es el punto de entrada de todos los programas de C#; tenga en cuenta que no es necesario crear una instancia de la clase contenedora para llamar al método Main. Otro método estático que se utiliza normalmente es WriteLine en la clase Console. Observe la diferencia de sintaxis cuando se tiene acceso a métodos estáticos; puede utilizar el nombre de clase, no el nombre de instancia, en la parte izquierda del operador de punto: Console.WriteLine.
Cuando declara un campo de clase estático, todas las instancias de esa clase compartirán ese campo. Si se declarara size como estático en el ejemplo de código siguiente y un objeto Animal cambiara el valor, éste se cambiaría para todos los objetos de tipo Animal.
Una clase estática es una cuyos miembros son todos estáticos. Las clases, métodos y campos estáticos son útiles en ciertos escenarios por razones de rendimiento y eficacia. Sin embargo, pueden surgir errores casi imperceptibles si se supone que un campo es un campo de instancia cuando de hecho es estático. Para obtener más información, vea Clases estáticas y sus miembros (Guía de programación de C#).
Clases y archivos
Cada programa de C# tiene al menos una clase. Al diseñar el programa, es una buena práctica, aunque no es un requisito, mantener una clase única en cada archivo de código fuente (.cs). Si utiliza el entorno de desarrollo integrado (IDE) de C# para crear las clases, éste, a la vez, creará un nuevo archivo de código en forma automática.
Encapsulación
Una clase representa normalmente las características de una cosa y las acciones que puede realizar. Por ejemplo, para representar un animal como una clase de C#, puede asignarle un tamaño, velocidad y fuerza, que se representan como números, y algunas funciones como MoveLeft(), MoveRight(), SpeedUp(), Stop(), etc., en las que podría escribir código para que el "animal" realice esas acciones. En C#, la clase animal tendría la apariencia siguiente:
public class Animal
{
private int size;
private float speed;
private int strength;
public void MoveLeft() // method
{
// code goes here...
}
// other methods go here...
}
Si examina la .NET Framework Class Library, observará que cada clase representa una "cosa", como XmlDocument, String o Form, y cada una de ellas tiene varias acciones que puede realizar (métodos), características que se pueden leer y, a veces, modificar (propiedades), y notificaciones (eventos) que produce cuando se realiza una acción concreta. Los métodos, propiedades y eventos, junto con todas las demás variables internas y constantes (campos), se conocen como miembros de la clase.
La agrupación de miembros en clases no es sólo lógica, además permite ocultar datos y funciones a los que no desea que otro código tenga acceso. Este principio se conoce como encapsulación. Cuando explora las bibliotecas de clases de .NET Framework, está viendo sólo los miembros públicos de esas clases. Cada clase tiene probablemente miembros privados que esa clase o las relacionadas con ella utilizan internamente, pero su finalidad no es que los utilicen las aplicaciones. Cuando cree sus propias clases, decidirá qué miembros deberían ser públicos y cuáles deberían ser privados.
Herencia
Una clase puede heredar de otra, lo que significa que incluye todos los miembros, tanto públicos como privados, de la clase original, más los miembros adicionales que define. La clase original se denomina clase base y la nueva clase se denomina clase derivada. Una clase derivada se crea para representar algo que es un tipo más especializado de la clase base. Por ejemplo, podría definir una clase Cat que hereda de Animal. Cat puede hacer lo mismo que Animal, más una acción única adicional. El código C# tiene la apariencia siguiente:
public class Cat : Animal
{
public void Purr()
{
}
}
La notación Cat : Animal indica que Cat hereda de Animal y, por tanto, Cat también tiene un método MoveLeft y tres variables privadas: size, speed y strength. Si define una clase SiameseCat que hereda de Cat, tendrá todos los miembros de Cat más todos los miembros de Animal.
Polimorfismo
En el campo de la programación, polimorfismo hace referencia a la capacidad de una clase derivada para redefinir o reemplazar los métodos que hereda de una clase base. Esto se hace cuando es necesario realizar una acción específica en un método que es diferente o no está definido en la clase base. Por ejemplo, como el método Animal.MoveLeft tiene que ser muy general a fin de que sea válido para todos los animales, probablemente es muy simple, por ejemplo: "cambiar la orientación para que la cabeza del anima apunte en la dirección X". Sin embargo, en la clase Cat, esto podría no ser suficiente. Podría ser necesario especificar cómo Cat mueve sus patas y cola mientras gira. Además, si también se define una clase Fish o Bird, probablemente habría que reemplazar el método MoveLeft de diferentes maneras para cada una de esas clases. Como el comportamiento del método MoveLeft se puede personalizar para una clase concreta, el código que crea la clase y llama a sus métodos no tiene un método independiente para cada animal del mundo. Siempre y cuando el objeto herede de Amimal, el código de llamada puede llamar simplemente al método MoveLeft para que se invoque la versión del método propia del objeto.
Constructores
Cada clase tiene un constructor: un método que comparte el mismo nombre que la clase. Se llama al constructor cuando se crea un objeto basado en la definición de clase. Los constructores establecen normalmente los valores iniciales de las variables definidas en la clase. Esto no es necesario si los valores iniciales van a ser cero para los tipos de datos numéricos, false para los tipos de datos booleanos o null para los tipos de referencia, ya que estos tipos de datos se inicializan automáticamente.
Puede definir constructores con cualquier número de parámetros. Los constructores que no tienen parámetros se denominan constructores predeterminados. En el ejemplo siguiente se define una clase con un constructor predeterminado y un constructor que toma una cadena y, a continuación, se utilizan ambos:
class SampleClass
{
string greeting;
public SampleClass()
{
greeting = "Hello, World";
}
public SampleClass(string message)
{
greeting = message;
}
public void SayHello()
{
System.Console.WriteLine(greeting);
}
}
class Program
{
static void Main(string[] args)
{
// Use default constructor.
SampleClass sampleClass1 = new SampleClass();
sampleClass1.SayHello();
// Use constructor that takes a string parameter.
SampleClass sampleClass2 = new SampleClass("Hello, Mars");
sampleClass2.SayHello();
}
}
Sobrecarga de operadores
La creación de métodos diferentes con el mismo nombre, en la SampleClass() de ejemplo anterior, se denomina sobrecarga. El compilador sabe qué método utilizar porque la lista de argumentos, si existe, se proporciona cada vez que se crea un objeto. La sobrecarga puede hacer que el código sea más flexible y legible.
Destructores
Si ha utilizado C++, ya conoce los destructores. Debido al sistema de recolección automática de elementos no utilizados de C#, no es probable que tenga que implementar un destructor a menos que la clase utilice recursos no administrados. Para obtener más información, vea Destructores (Guía de programación de C#).
Estructuras
Una estructura es un tipo que es similar a una clase de muchas maneras, excepto en que no admite la herencia. Para obtener más información, vea Estructuras (Visual C# Express).
Vea también
Tareas
Cómo: Llamar a un método en un objeto (Visual C#)
Cómo: Heredar de una clase (Visual C#)