Ir al contenido principal

Clases y objetos en C#

Introducción

Las clases y los objetos constituyen la base fundamental de la programación orientada a objetos en C#. Una clase es como un plano o plantilla que define las características y comportamientos que tendrán los objetos creados a partir de ella, mientras que un objeto es una instancia específica de esa clase. Este concepto es similar a como un plano arquitectónico define la estructura de una casa, pero la casa construida es el objeto real que podemos habitar.

Comprender las clases y objetos es esencial para dominar C#, ya que todo en este lenguaje está basado en este paradigma. Incluso el programa más simple que hemos escrito utiliza clases, aunque no hayamos sido conscientes de ello. En este artículo aprenderemos a crear nuestras propias clases, instanciar objetos y trabajar con sus miembros.

¿Qué es una clase?

Una clase es un tipo de datos personalizado que agrupa variables (llamadas campos o propiedades) y métodos relacionados en una sola unidad. Es una plantilla que describe qué datos puede almacenar un objeto y qué operaciones puede realizar.

Elementos básicos de una clase

Elemento Descripción Propósito
Campos Variables que almacenan datos Representan el estado del objeto
Propiedades Acceso controlado a los campos Encapsulan el acceso a los datos
Métodos Funciones que realizan operaciones Definen el comportamiento del objeto
Constructor Método especial de inicialización Configura el estado inicial del objeto

Sintaxis básica de una clase

public class NombreDeLaClase
{
    // Campos
    private tipo campo;
    
    // Propiedades
    public tipo Propiedad { get; set; }
    
    // Constructor
    public NombreDeLaClase()
    {
        // Código de inicialización
    }
    
    // Métodos
    public tipo NombreDelMetodo()
    {
        // Código del método
        return valor;
    }
}

Creando nuestra primera clase

Vamos a crear una clase Persona que represente a una persona con características básicas:

public class Persona
{
    // Campos privados
    private string nombre;
    private int edad;
    private string email;
    
    // Constructor
    public Persona(string nombre, int edad, string email)
    {
        this.nombre = nombre;
        this.edad = edad;
        this.email = email;
    }
    
    // Método para mostrar información
    public void MostrarInformacion()
    {
        Console.WriteLine($"Nombre: {nombre}");
        Console.WriteLine($"Edad: {edad} años");
        Console.WriteLine($"Email: {email}");
    }
    
    // Método para saludar
    public string Saludar()
    {
        return $"¡Hola! Soy {nombre} y tengo {edad} años.";
    }
    
    // Método para validar si es mayor de edad
    public bool EsMayorDeEdad()
    {
        return edad >= 18;
    }
}

En este ejemplo, la clase Persona tiene:

  • Tres campos privados para almacenar los datos
  • Un constructor que inicializa estos datos
  • Tres métodos que definen comportamientos específicos

¿Qué es un objeto?

Un objeto es una instancia específica de una clase. Es la materialización de la plantilla que representa la clase, con valores concretos para sus campos y la capacidad de ejecutar sus métodos.

Proceso de creación de objetos

Paso Acción Descripción
1 Declaración Se declara una variable del tipo de la clase
2 Instanciación Se usa new para crear el objeto en memoria
3 Inicialización Se ejecuta el constructor para configurar el estado inicial
4 Uso Se accede a los miembros del objeto mediante el operador punto

Creando y usando objetos

Una vez que tenemos nuestra clase definida, podemos crear objetos (instancias) de ella:

class Program
{
    static void Main()
    {
        // Crear objetos de la clase Persona
        Persona persona1 = new Persona("Ana García", 25, "ana@email.com");
        Persona persona2 = new Persona("Carlos López", 17, "carlos@email.com");
        
        // Usar los métodos de los objetos
        Console.WriteLine("=== Información de las personas ===");
        
        persona1.MostrarInformacion();
        Console.WriteLine(persona1.Saludar());
        Console.WriteLine($"¿Es mayor de edad? {persona1.EsMayorDeEdad()}");
        
        Console.WriteLine(); // Línea en blanco
        
        persona2.MostrarInformacion();
        Console.WriteLine(persona2.Saludar());
        Console.WriteLine($"¿Es mayor de edad? {persona2.EsMayorDeEdad()}");
    }
}

Salida esperada:

=== Información de las personas ===
Nombre: Ana García
Edad: 25 años
Email: ana@email.com
¡Hola! Soy Ana García y tengo 25 años.
¿Es mayor de edad? True

Nombre: Carlos López
Edad: 17 años
Email: carlos@email.com
¡Hola! Soy Carlos López y tengo 17 años.
¿Es mayor de edad? False

La palabra clave this

La palabra clave this hace referencia a la instancia actual del objeto. Es especialmente útil cuando hay ambigüedad entre parámetros del método y campos de la clase:

public class CuentaBancaria
{
    private double saldo;
    private string titular;
    
    public CuentaBancaria(string titular, double saldoInicial)
    {
        // 'this' distingue entre el campo y el parámetro
        this.titular = titular;
        this.saldo = saldoInicial;
    }
    
    public void Depositar(double cantidad)
    {
        // Aquí no es necesario 'this' porque no hay ambigüedad
        saldo += cantidad;
        Console.WriteLine($"Depósito realizado. Saldo actual: {saldo:C}");
    }
    
    public bool Retirar(double cantidad)
    {
        if (cantidad <= saldo)
        {
            saldo -= cantidad;
            Console.WriteLine($"Retiro realizado. Saldo actual: {saldo:C}");
            return true;
        }
        else
        {
            Console.WriteLine("Fondos insuficientes");
            return false;
        }
    }
    
    public string ObtenerInformacion()
    {
        return $"Titular: {titular}, Saldo: {saldo:C}";
    }
}

Ejemplo práctico: Sistema de biblioteca

Veamos un ejemplo más complejo con una clase Libro que podría formar parte de un sistema de gestión de biblioteca:

public class Libro
{
    // Campos privados
    private string titulo;
    private string autor;
    private string isbn;
    private bool prestado;
    private DateTime fechaPrestamo;
    
    // Constructor
    public Libro(string titulo, string autor, string isbn)
    {
        this.titulo = titulo;
        this.autor = autor;
        this.isbn = isbn;
        this.prestado = false; // Por defecto, no está prestado
    }
    
    // Método para prestar el libro
    public bool Prestar()
    {
        if (!prestado)
        {
            prestado = true;
            fechaPrestamo = DateTime.Now;
            Console.WriteLine($"El libro '{titulo}' ha sido prestado el {fechaPrestamo.ToShortDateString()}");
            return true;
        }
        else
        {
            Console.WriteLine($"El libro '{titulo}' ya está prestado");
            return false;
        }
    }
    
    // Método para devolver el libro
    public bool Devolver()
    {
        if (prestado)
        {
            prestado = false;
            TimeSpan tiempoPrestado = DateTime.Now - fechaPrestamo;
            Console.WriteLine($"El libro '{titulo}' ha sido devuelto después de {tiempoPrestado.Days} días");
            return true;
        }
        else
        {
            Console.WriteLine($"El libro '{titulo}' no estaba prestado");
            return false;
        }
    }
    
    // Método para obtener información del libro
    public string ObtenerInformacion()
    {
        string estado = prestado ? $"Prestado desde {fechaPrestamo.ToShortDateString()}" : "Disponible";
        return $"Título: {titulo}\nAutor: {autor}\nISBN: {isbn}\nEstado: {estado}";
    }
    
    // Método para verificar disponibilidad
    public bool EstaDisponible()
    {
        return !prestado;
    }
}

Ahora podemos usar esta clase para gestionar libros:

class Program
{
    static void Main()
    {
        // Crear algunos libros
        Libro libro1 = new Libro("El Quijote", "Miguel de Cervantes", "978-84-376-0494-7");
        Libro libro2 = new Libro("Cien años de soledad", "Gabriel García Márquez", "978-84-376-0495-4");
        
        Console.WriteLine("=== Estado inicial de los libros ===");
        Console.WriteLine(libro1.ObtenerInformacion());
        Console.WriteLine();
        Console.WriteLine(libro2.ObtenerInformacion());
        Console.WriteLine();
        
        Console.WriteLine("=== Operaciones de préstamo ===");
        libro1.Prestar(); // Prestamos el primer libro
        libro1.Prestar(); // Intentamos prestarlo de nuevo
        Console.WriteLine();
        
        Console.WriteLine("=== Estado después del préstamo ===");
        Console.WriteLine(libro1.ObtenerInformacion());
        Console.WriteLine();
        
        Console.WriteLine("=== Verificar disponibilidad ===");
        Console.WriteLine($"¿Está disponible '{libro1.ObtenerInformacion()}'? {libro1.EstaDisponible()}");
        Console.WriteLine($"¿Está disponible '{libro2.ObtenerInformacion()}'? {libro2.EstaDisponible()}");
        
        // Simulamos el paso del tiempo y devolvemos el libro
        Console.WriteLine("\n=== Devolución del libro ===");
        libro1.Devolver();
    }
}

Múltiples objetos de la misma clase

Una de las grandes ventajas de las clases es que podemos crear múltiples objetos, cada uno con su propio estado independiente:

class Program
{
    static void Main()
    {
        // Crear múltiples cuentas bancarias
        CuentaBancaria cuenta1 = new CuentaBancaria("María Fernández", 1000);
        CuentaBancaria cuenta2 = new CuentaBancaria("Pedro Jiménez", 500);
        CuentaBancaria cuenta3 = new CuentaBancaria("Laura Martín", 1500);
        
        Console.WriteLine("=== Estado inicial de las cuentas ===");
        Console.WriteLine(cuenta1.ObtenerInformacion());
        Console.WriteLine(cuenta2.ObtenerInformacion());
        Console.WriteLine(cuenta3.ObtenerInformacion());
        
        Console.WriteLine("\n=== Operaciones bancarias ===");
        cuenta1.Depositar(200);
        cuenta2.Retirar(100);
        cuenta3.Retirar(2000); // Intento de retiro con fondos insuficientes
        
        Console.WriteLine("\n=== Estado final de las cuentas ===");
        Console.WriteLine(cuenta1.ObtenerInformacion());
        Console.WriteLine(cuenta2.ObtenerInformacion());
        Console.WriteLine(cuenta3.ObtenerInformacion());
    }
}

Cada objeto mantiene su propio estado independiente. Las operaciones en cuenta1 no afectan a cuenta2 o cuenta3.

Diferencias entre clases y objetos

Aspecto Clase Objeto
Naturaleza Plantilla o molde Instancia específica
Memoria No ocupa memoria para datos Ocupa memoria en tiempo de ejecución
Cantidad Una definición por programa Pueden existir múltiples instancias
Estado Define qué datos puede tener Tiene valores específicos para esos datos
Momento Se define en tiempo de compilación Se crea en tiempo de ejecución

Buenas prácticas para clases y objetos

  1. Nombres descriptivos: Usa nombres que describan claramente el propósito de la clase
  2. Responsabilidad única: Cada clase debe tener una responsabilidad específica
  3. Encapsulación: Mantén los campos privados y proporciona acceso controlado
  4. Constructores útiles: Asegúrate de que los objetos se inicialicen en un estado válido
  5. Métodos con propósito: Cada método debe realizar una tarea específica y bien definida

Resumen

Las clases y objetos son los pilares fundamentales de la programación orientada a objetos en C#. Una clase es una plantilla que define la estructura y comportamiento de los objetos, mientras que un objeto es una instancia específica de esa clase con valores concretos. Hemos aprendido a crear clases con campos, constructores y métodos, así como a instanciar objetos y utilizar sus miembros. La palabra clave this nos permite referenciar la instancia actual, y cada objeto mantiene su propio estado independiente. Este conocimiento forma la base para conceptos más avanzados como propiedades, herencia y polimorfismo que exploraremos en los siguientes artículos.