Con esto se cierra el Módulo 2: hasta ahora, cada libro de BiblioTechConsola era un puñado de variables sueltas (un string para el título, otro para el autor, otro para el ISBN, un bool para la disponibilidad) que había que declarar y mantener sincronizadas a mano, una vez por cada libro. Si BiblioTech gestionara cien libros, harían falta cuatrocientas variables —o cuatro arrays paralelos donde la posición i de cada uno tuviera que corresponder al mismo libro, con el riesgo constante de desincronizarlos. En este Módulo 3: Programación Orientada a Objetos vas a resolver ese problema de raíz aprendiendo a definir tus propios tipos: las clases. Una clase agrupa en un único lugar los datos (propiedades) y, más adelante, el comportamiento (métodos) de un concepto del mundo real —un libro, un socio, un préstamo—, de modo que cada libro de BiblioTech pase a ser un único objeto autocontenido en lugar de cuatro variables dispersas. Esta primera lección sienta las bases: qué es una clase, qué es un objeto, cómo se define una clase con propiedades, y cómo se crean objetos a partir de ella con new.

Contenido

  1. De variables sueltas a objetos: por qué las clases
  2. ¿Qué es una clase? ¿Qué es un objeto?
  3. Definir una clase con la palabra clave class
  4. Campos y propiedades ({ get; set; })
  5. Creando objetos con new
  6. Inicializadores de objeto
  7. Múltiples objetos de la misma clase
  8. Clases frente a tipos primitivos: tipos por referencia

  1. De variables sueltas a objetos: por qué las clases

Recupera cómo se representaba un libro en los módulos anteriores:

string tituloLibro1 = "Cien anos de soledad";
string autorLibro1 = "Gabriel Garcia Marquez";
string isbnLibro1 = "978-84-376-0494-7";
bool disponibleLibro1 = true;

string tituloLibro2 = "Rayuela";
string autorLibro2 = "Julio Cortazar";
string isbnLibro2 = "978-84-376-0495-4";
bool disponibleLibro2 = false;

Fíjate en el problema: nada en el código indica que tituloLibro1, autorLibro1, isbnLibro1 y disponibleLibro1 pertenecen al mismo libro; es una convención que solo existe en la cabeza de quien programa, sostenida a base de nombrar cuidadosamente cada variable. Añadir un tercer libro significa copiar y pegar cuatro líneas más, con el nombre Libro3, y confiar en no equivocarse. Este módulo resuelve esto agrupando esos cuatro datos en un único tipo llamado Libro, de modo que cada libro real de la biblioteca sea representado por un solo objeto.

  1. ¿Qué es una clase? ¿Qué es un objeto?

Una clase es una plantilla (o "molde") que describe qué datos y qué comportamiento tendrán los objetos creados a partir de ella. No es, en sí misma, un libro concreto: es la definición de "qué es y qué puede hacer un libro" en el sistema. Un objeto es una instancia concreta de una clase: un libro real, con sus propios valores para el título, el autor, el ISBN y la disponibilidad.

La relación entre clase y objeto es la misma que entre un plano de una casa y las casas construidas con ese plano:

Concepto Analogía (plano de una casa) En BiblioTech
Clase El plano: define que toda casa tiene puertas, ventanas, habitaciones Libro: define que todo libro tiene título, autor, ISBN, disponibilidad
Objeto Una casa concreta, construida siguiendo el plano Un ejemplar concreto, por ejemplo "Rayuela"
Varios objetos Muchas casas distintas, construidas con el mismo plano Muchos libros distintos, todos con la misma estructura

De un mismo plano se pueden construir tantas casas como se quiera, cada una con su propia dirección y sus propios muebles; de una misma clase se pueden crear tantos objetos como se quiera, cada uno con sus propios valores.

  1. Definir una clase con la palabra clave class

Una clase se define con la palabra clave class seguida de un nombre (por convención, en PascalCase, empezando por mayúscula) y un cuerpo entre llaves { }:

class Libro
{
    // Aquí irán las propiedades de un libro
}

Esto ya es una clase válida, aunque todavía vacía: no describe ningún dato. El siguiente paso es indicar qué información tiene cada libro.

Convención de nombres: las clases en C# se nombran en PascalCase (Libro, Socio, Prestamo), a diferencia de las variables y parámetros, que usan camelCase (titulo, numeroSocio). Este curso seguirá esta convención de forma estricta a partir de ahora.

  1. Campos y propiedades ({ get; set; })

Dentro de una clase, los datos se pueden representar de dos formas: campos y propiedades.

Un campo es la forma más simple: una variable declarada directamente dentro de la clase.

class Libro
{
    public string titulo;
    public string autor;
}

Sin embargo, en C# lo habitual —y lo recomendado— es usar propiedades, que se declaran de forma parecida a un campo pero incluyen { get; set; } a continuación:

class Libro
{
    public string Titulo { get; set; }
    public string Autor { get; set; }
    public string Isbn { get; set; }
    public bool Disponible { get; set; }
}

Esta sintaxis se llama propiedad autoimplementada (auto-implemented property): get permite leer el valor, y set permite asignarlo, sin que tengas que escribir tú el código que almacena el dato internamente (el compilador genera ese almacenamiento oculto por ti). A efectos prácticos, de momento se comportan igual que un campo público, pero con dos ventajas importantes que irán cobrando sentido a lo largo del módulo:

  • Su nombre se escribe en PascalCase (Titulo, no titulo), siguiendo la convención de C# para todo lo que es visible desde fuera de la clase.
  • Más adelante (lección de Encapsulamiento) podrás añadir lógica de validación dentro del set sin cambiar cómo se usa la propiedad desde fuera —algo que un campo público no permite hacer de forma limpia.
Campo (public string titulo;) Propiedad (public string Titulo { get; set; })
Sintaxis Variable declarada directamente Añade { get; set; }
Convención de nombre camelCase PascalCase
Permite añadir validación después sin romper el código que la usa No, de forma limpia
Uso recomendado en C# para datos expuestos públicamente No

A partir de ahora, Libro (y el resto de clases del curso) se definirán siempre con propiedades, no con campos públicos sueltos.

Esta será la definición de partida de Libro para todo el módulo:

class Libro
{
    public string Titulo { get; set; }
    public string Autor { get; set; }
    public string Isbn { get; set; }
    public bool Disponible { get; set; }
}

  1. Creando objetos con new

Definir la clase Libro no crea ningún libro todavía: solo describe cómo será cualquier libro. Para crear un objeto concreto —una instancia— se usa la palabra clave new, seguida del nombre de la clase y paréntesis:

Libro libro1 = new Libro();
libro1.Titulo = "Cien anos de soledad";
libro1.Autor = "Gabriel Garcia Marquez";
libro1.Isbn = "978-84-376-0494-7";
libro1.Disponible = true;

Console.WriteLine(libro1.Titulo); // Cien anos de soledad
Console.WriteLine(libro1.Disponible); // True

Analicemos esta línea clave: Libro libro1 = new Libro();

  • Libro (antes del nombre de variable) indica el tipo de la variable libro1: será un objeto de tipo Libro.
  • new Libro() crea un objeto nuevo en memoria, siguiendo la plantilla de la clase Libro, y devuelve una referencia a él.
  • libro1 es la variable que guarda esa referencia, y a partir de ahí se usa el operador . (punto) para acceder a sus propiedades: libro1.Titulo, libro1.Autor, etc.

Cada propiedad de un objeto recién creado con new Libro() toma su valor por defecto hasta que se le asigna uno explícitamente: null para string (por eso hay que asignarlo antes de usarlo, o el programa fallará al leerlo), false para bool, 0 para tipos numéricos como int.

  1. Inicializadores de objeto

Asignar cada propiedad en una línea separada, como en el ejemplo anterior, funciona pero es repetitivo. C# ofrece una alternativa más compacta llamada inicializador de objeto, que asigna varias propiedades entre llaves { } justo después de new Libro():

Libro libro2 = new Libro
{
    Titulo = "Rayuela",
    Autor = "Julio Cortazar",
    Isbn = "978-84-376-0495-4",
    Disponible = false
};

Console.WriteLine(libro2.Titulo); // Rayuela

Este código es equivalente a crear el objeto con new Libro() y luego asignar cada propiedad por separado, pero resulta más legible cuando se inicializan varias propiedades a la vez, ya que agrupa visualmente "estos valores pertenecen a este objeto".

  1. Múltiples objetos de la misma clase

La ventaja frente a las variables sueltas del Módulo 1 se aprecia mejor con varios libros a la vez: cada objeto Libro es completamente independiente de los demás, aunque comparta la misma estructura definida por la clase.

Libro libro1 = new Libro { Titulo = "Cien anos de soledad", Autor = "Gabriel Garcia Marquez", Isbn = "978-84-376-0494-7", Disponible = true };
Libro libro2 = new Libro { Titulo = "Rayuela", Autor = "Julio Cortazar", Isbn = "978-84-376-0495-4", Disponible = false };
Libro libro3 = new Libro { Titulo = "Ficciones", Autor = "Jorge Luis Borges", Isbn = "978-84-376-0496-1", Disponible = true };

Console.WriteLine($"{libro1.Titulo} - Disponible: {libro1.Disponible}");
Console.WriteLine($"{libro2.Titulo} - Disponible: {libro2.Disponible}");
Console.WriteLine($"{libro3.Titulo} - Disponible: {libro3.Disponible}");

Cada uno de los tres objetos (libro1, libro2, libro3) tiene sus propios valores para Titulo, Autor, Isbn y Disponible, sin ninguna posibilidad de confundir el título de uno con la disponibilidad de otro: toda la información de un libro concreto vive dentro de su propio objeto. Modificar libro2.Disponible no afecta en absoluto a libro1 ni a libro3.

  1. Clases frente a tipos primitivos: tipos por referencia

Una diferencia importante entre un Libro y un tipo primitivo como int o bool es que las clases son tipos por referencia: una variable de tipo Libro no contiene el objeto en sí, sino una referencia (una especie de "dirección") que apunta a él en memoria. Esto tiene una consecuencia práctica que conviene ver desde el principio:

Libro original = new Libro { Titulo = "Rayuela", Disponible = true };
Libro copia = original; // copia no es un libro nuevo: apunta al MISMO objeto que original

copia.Disponible = false;

Console.WriteLine(original.Disponible); // False -- ¡tambien cambio el original!

Como copia y original apuntan al mismo objeto en memoria, modificar copia.Disponible también se refleja al leer original.Disponible: no son dos libros independientes, son dos nombres distintos para el mismo libro. Esto contrasta con los tipos primitivos (int, bool, double...), que son tipos por valor: al asignar int b = a;, b recibe una copia independiente del valor de a. Retomaremos esta distinción con más detalle en la última lección del módulo, cuando comparemos clases con struct.

Errores Comunes y Consejos

  • Olvidar new: escribir Libro libro1; declara una variable capaz de referenciar un Libro, pero no crea ningún objeto; intentar usar libro1.Titulo antes de asignarle new Libro() provoca un error de compilación (o, en ciertos contextos, una excepción en tiempo de ejecución si la variable vale null).
  • Confundir la clase con el objeto: Libro es la plantilla; libro1, libro2, libro3 son objetos concretos creados a partir de ella. Es un error habitual en las primeras lecciones hablar de "la clase libro1" cuando en realidad es un objeto.
  • Usar campos públicos sueltos por costumbre: en C# se prefieren las propiedades ({ get; set; }) a los campos públicos, precisamente porque permiten añadir validación más adelante sin romper el código que ya las usa. Acostúmbrate a esta sintaxis desde ya.
  • No caer en que las clases son tipos por referencia: como se ha visto en el último apartado, copiar una variable de tipo clase no duplica el objeto; ambas variables comparten el mismo objeto en memoria. Este detalle explica comportamientos que, de otro modo, parecerían errores extraños.
  • Consejo: nombra las clases siempre en singular y en PascalCase (Libro, no Libros ni libro): una clase describe un único concepto, aunque luego crees muchos objetos de ella.

Ejercicios

  1. Define una clase Libro con las propiedades Titulo (string), Autor (string), Isbn (string) y Disponible (bool), todas ellas como propiedades autoimplementadas ({ get; set; }).

  2. Usando la clase del ejercicio anterior, crea un objeto Libro llamado miLibro asignando sus propiedades una a una (sin inicializador de objeto) con los datos: título "El Aleph", autor "Jorge Luis Borges", ISBN "978-84-376-0497-8" y disponible true. Muestra por consola el título y la disponibilidad.

  3. Crea dos objetos Libro distintos usando el inicializador de objeto (new Libro { ... }), con datos diferentes para cada uno, y muestra por consola el título de cada uno seguido de su disponibilidad, usando interpolación de cadenas.

Soluciones

class Libro
{
    public string Titulo { get; set; }
    public string Autor { get; set; }
    public string Isbn { get; set; }
    public bool Disponible { get; set; }
}
Libro miLibro = new Libro();
miLibro.Titulo = "El Aleph";
miLibro.Autor = "Jorge Luis Borges";
miLibro.Isbn = "978-84-376-0497-8";
miLibro.Disponible = true;

Console.WriteLine(miLibro.Titulo);
Console.WriteLine(miLibro.Disponible);

Se crea el objeto vacío con new Libro() y después se asigna cada propiedad por separado; al final se muestran el título ("El Aleph") y la disponibilidad (True).

Libro libroA = new Libro { Titulo = "Ficciones", Autor = "Jorge Luis Borges", Isbn = "978-84-376-0496-1", Disponible = true };
Libro libroB = new Libro { Titulo = "Rayuela", Autor = "Julio Cortazar", Isbn = "978-84-376-0495-4", Disponible = false };

Console.WriteLine($"{libroA.Titulo} - Disponible: {libroA.Disponible}");
Console.WriteLine($"{libroB.Titulo} - Disponible: {libroB.Disponible}");

Cada objeto se crea e inicializa en un solo paso gracias al inicializador de objeto; al mostrarlos por consola se comprueba que cada uno mantiene sus propios valores de forma independiente.

Conclusión

En esta lección has dado el paso más importante del módulo: has aprendido qué es una clase, qué es un objeto, y cómo definir tu primera clase propia, Libro, con propiedades autoimplementadas (Titulo, Autor, Isbn, Disponible). Ya sabes crear objetos con new, asignarles valores propiedad a propiedad o mediante inicializadores de objeto, y por qué las clases son tipos por referencia. Con esto, BiblioTechConsola empieza a dejar atrás las variables sueltas: cada libro es ahora un objeto autocontenido.

Todavía falta una pieza importante: por ahora, un objeto Libro es solo un contenedor de datos, sin ningún comportamiento propio —para prestarlo o mostrarlo por pantalla seguimos necesitando código externo a la clase. En la próxima lección, Métodos, aprenderás a añadir comportamiento directamente a Libro (como Prestar(), Devolver() o MostrarFicha()), de modo que cada objeto sepa hacer cosas por sí mismo, no solo almacenar datos.

Curso de Programación en C#

Módulo 1: Introducción a C#

Módulo 2: Estructuras de Control

Módulo 3: Programación Orientada a Objetos

Módulo 4: Conceptos Avanzados de C#

Módulo 5: Trabajando con Datos

Módulo 6: Temas Avanzados

Módulo 7: Construcción de Aplicaciones

Módulo 8: Mejores Prácticas y Patrones de Diseño

Módulo 9: Proyecto Final

© Copyright 2026. Todos los derechos reservados