Clases, Objetos, Propiedades y Métodos en C#
Aprende cómo las clases, objetos, propiedades y métodos en C# forman la base de la programación orientada a objetos.
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: Accesible desde cualquier parte.
- private: Accesible solo dentro de la clase.
- protected: Accesible en la clase y sus subclases.
- internal: Accesible dentro del mismo ensamblado.
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();
En resumen
- Clase: Plantilla que define datos + comportamientos.
- Objeto: Instancia concreta creada a partir de una clase.
- Propiedad: Acceso controlado a los datos (encapsulación).
- Método: Define lo que un objeto puede hacer (instancia o estático).
- Modificadores de acceso: Controlan visibilidad con public, private, protected, internal.
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 con un método Validate().
El resultado de la validación se devuelve mediante un enum ValidationResult.
De esta manera, se puede identificar claramente la causa del 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() comprueba la validez de los datos ingresados y devuelve un enum.
En lugar de devolver simplemente true/false, indica la causa exacta del error.
Por ejemplo: nombre faltante, teléfono vacío o no numérico.
Este enfoque hace que la gestión de errores sea más clara y más fácil de mantener.
NameMissing: Falta el nombre de la empresa.PhoneMissing: No se proporcionó el número de teléfono.PhoneInvalid: El número de teléfono contiene caracteres no numéricos.AddressMissing: Falta la dirección.Success: Todas las validaciones fueron correctas.