Cargando...

Variables, tipos de datos y auto en C++

Aprende variables, tipos de datos y el uso de auto en C++ con ejemplos prácticos de deducción de tipos.

En la Programación Orientada a Objetos (OOP), una clase es una plantilla que agrupa los datos (propiedades) y los comportamientos (métodos) de un concepto bajo una sola estructura. Las instancias creadas a partir de esta plantilla se llaman objetos. Las propiedades se utilizan para acceder a los datos y los métodos definen los comportamientos.


¿Qué es una Clase?

Una clase es una plantilla utilizada para modelar un concepto o entidad en software. Define propiedades, campos y métodos. Por ejemplo, una clase Product puede almacenar datos como el nombre y el precio de un producto, además de incluir comportamientos como “imprimir información”.


public class Product
{
    private decimal _price;

    public string Name { get; set; } = string.Empty;

    public decimal Price
    {
        get => _price;
        set => _price = value < 0 ? 0 : value; // precio negativo evitado
    }

    public void PrintInfo()
    {
        Console.WriteLine($"{Name} - {Price:0.00} EUR");
    }
}

Crear un Objeto

Para crear una instancia concreta (objeto) de una clase, se utiliza la palabra clave new. Esto crea un objeto en memoria de acuerdo con la definición de la clase. Se pueden asignar valores a las propiedades y llamar a los métodos.


var notebook = new Product();
notebook.Name = "Notebook";
notebook.Price = 45m;
notebook.PrintInfo();

// Salida:
Notebook - 45.00 EUR

Los objetos también se pueden inicializar de forma más concisa con un object initializer:


var pen = new Product { Name = "Pen", Price = 12.5m };
pen.PrintInfo();

Tipos de Propiedades

Las propiedades proporcionan acceso controlado a los datos dentro de una clase. En lugar de exponer directamente los campos, el uso de propiedades permite agregar validaciones y reglas de negocio.

Propiedades automáticas: La opción más práctica cuando no se necesita lógica adicional.


public class Customer
{
    public int Id { get; set; }
    public string FullName { get; set; } = string.Empty;
}

Propiedad con campo privado: Proporciona control mediante un campo privado.


public class Temperature
{
    private double _celsius;

    public double Celsius
    {
        get => _celsius;
        set => _celsius = value;
    }

    public double Fahrenheit => (_celsius * 9 / 5) + 32; // solo lectura
}

Propiedad init-only (C# 9+): Solo se puede establecer al crear el objeto, no después.


public class User
{
    public string Username { get; init; } = string.Empty;
    public string Email { get; init; } = string.Empty;
}

var u = new User { Username = "john", Email = "j@example.com" };
// u.Username = "michael"; // error: propiedad init-only

Métodos

Los métodos definen las acciones que un objeto puede realizar. Pueden aceptar parámetros y devolver valores. Es posible definir varios métodos con el mismo nombre pero diferentes firmas (sobrecarga).


public class MathUtil
{
    public static int Sum(int a, int b) => a + b;
    public static int Sum(int a, int b, int c) => a + b + c; // sobrecarga
}

int x = MathUtil.Sum(2, 3);     // 5
int y = MathUtil.Sum(1, 2, 3);  // 6

Métodos de instancia: llamados a través de un objeto. Métodos estáticos: llamados directamente desde la clase.


Modificadores de Acceso

En C#, la visibilidad de las clases y sus miembros se controla con modificadores como public, private, protected e internal:

Los modificadores de acceso definen desde qué partes del programa se puede usar una clase o sus miembros (propiedades, métodos, campos). Por ejemplo, los miembros private solo son accesibles dentro de la clase donde están definidos, evitando interferencias externas y garantizando la seguridad de los datos. Los miembros public son accesibles desde cualquier lugar y representan la interfaz pública de la clase. Los miembros protected son accesibles en la propia clase y en las clases derivadas, lo que facilita la herencia. Los miembros internal son accesibles dentro del mismo ensamblado, bloqueando el acceso desde otros proyectos. Este mecanismo responde a la pregunta “qué información debe exponerse y cuál debe permanecer encapsulada”, ayudando a reducir dependencias, aplicar el principio de encapsulación y construir una arquitectura clara y segura.


public class Account
{
    private decimal _balance; // solo dentro de la clase

    public decimal Balance { get; private set; } // solo lectura desde fuera

    protected string Owner { get; set; } = string.Empty; // utilizable en subclases

    internal string? Tag { get; set; } // accesible en el mismo proyecto

    public void Deposit(decimal amount)
    {
        if (amount <= 0) return;
        Balance += amount;
    }
}

Ejemplo: Sistema de Biblioteca Simple

En el siguiente ejemplo, se definen una clase Book y una clase de gestión LibraryService. Esto demuestra cómo crear, almacenar y procesar objetos.


public class Book
{
    public int Id { get; init; }
    public string Title { get; set; } = string.Empty;
    public string Author { get; set; } = string.Empty;

    public void Print() => Console.WriteLine($"{Id} - {Title} ({Author})");
}

public class LibraryService
{
    private readonly List<Book> _books = new();

    public void Add(Book b) => _books.Add(b);

    public Book? FindById(int id) => _books.FirstOrDefault(b => b.Id == id);

    public void PrintAll()
    {
        if (_books.Count == 0)
        {
            Console.WriteLine("La biblioteca está vacía.");
            return;
        }

        foreach (var b in _books)
            b.Print();
    }
}

// Uso
var lib = new LibraryService();

lib.Add(new Book
{
    Id = 1,
    Title = "Clean Code",
    Author = "Robert C. Martin"
});

lib.Add(new Book
{
    Id = 2,
    Title = "CLR via C#",
    Author = "Jeffrey Richter"
});

lib.PrintAll();

Resumen

  • Clase: Plantilla que define datos y comportamientos.
  • Objeto: Instancia concreta creada a partir de una clase.
  • Propiedad: Proporciona acceso controlado a los datos (encapsulación).
  • Método: Define lo que un objeto puede hacer (instancia o estático).
  • Modificadores de acceso: Controlan la visibilidad mediante public, private, protected e internal.

Artículos relacionados: Constructor, Destructor, this | Encapsulación, Herencia, Polimorfismo


Ejemplo: Información de Empresa y Validación

En este ejemplo, la clase Company no solo almacena los datos introducidos por el usuario, sino que también los valida mediante un método Validate(). El resultado de la validación se devuelve utilizando un enum personalizado llamado ValidationResult. De esta forma, es posible identificar claramente la causa de un error.


public enum ValidationResult
{
    Success,
    NameMissing,
    PhoneMissing,
    PhoneInvalid,
    AddressMissing
}

public class Company
{
    public string Name { get; set; } = string.Empty;
    public string Phone { get; set; } = string.Empty;
    public string Address { get; set; } = string.Empty;
    public string Sector { get; set; } = string.Empty;

    public void PrintInfo()
    {
        Console.WriteLine("=== Información de la Empresa ===");
        Console.WriteLine($"Nombre    : {Name}");
        Console.WriteLine($"Teléfono  : {Phone}");
        Console.WriteLine($"Dirección : {Address}");
        Console.WriteLine($"Sector    : {Sector}");
    }

    public ValidationResult Validate()
    {
        if (string.IsNullOrWhiteSpace(Name))
            return ValidationResult.NameMissing;

        if (string.IsNullOrWhiteSpace(Phone))
            return ValidationResult.PhoneMissing;

        if (!Phone.All(char.IsDigit))
            return ValidationResult.PhoneInvalid;

        if (string.IsNullOrWhiteSpace(Address))
            return ValidationResult.AddressMissing;

        return ValidationResult.Success;
    }
}

class Program
{
    static void Main()
    {
        var company = new Company();

        Console.Write("Ingrese el nombre de la empresa: ");
        company.Name = Console.ReadLine();

        Console.Write("Ingrese el teléfono: ");
        company.Phone = Console.ReadLine();

        Console.Write("Ingrese la dirección: ");
        company.Address = Console.ReadLine();

        Console.Write("Ingrese el sector: ");
        company.Sector = Console.ReadLine();

        var result = company.Validate();

        if (result == ValidationResult.Success)
        {
            Console.WriteLine();
            company.PrintInfo();
        }
        else
        {
            Console.WriteLine($"Error: {result}");
        }
    }
}

El método Validate() verifica si los datos introducidos son válidos y devuelve un enum. En lugar de devolver simplemente true/false, indica exactamente cuál es el problema. Por ejemplo, puede detectar si falta el nombre de la empresa, si el teléfono está vacío o si contiene caracteres no numéricos. Este enfoque hace que el manejo de errores sea más claro y más fácil de mantener.


Artículos relacionados