En el camino hacia la maestría del desarrollo de software, uno de los pilares fundamentales es comprender los principios de la programación orientada a objetos (POO). El encapsulamiento, como parte de estos principios, desempeña un rol crucial en la construcción de un código limpio y mantenible. A través del ejemplo práctico que iremos desarrollando a continuación, entenderemos cómo se implementa el encapsulamiento en C# y qué beneficios aporta a nuestro código.
¿Qué es el encapsulamiento en la programación orientada a objetos?
El encapsulamiento se refiere a la práctica de ocultar los detalles internos del funcionamiento de una clase y exponer únicamente aquello que es necesario para el resto del programa. Es uno de los cuatro principios fundamentales de la POO, junto con la abstracción, la herencia y el polimorfismo.
¿Cómo implementamos el encapsulamiento en C#?
Para llevar a cabo el encapsulamiento en C#, se utilizan modificadores de acceso y se estructuran las propiedades de las clases con métodos de acceso (getters) y de modificación (setters). Veamos cómo se pueden aplicar estos conceptos con un ejemplo práctico:
Propiedades públicas y privadas
Primero, definimos una propiedad privada que solo será accesible dentro de la clase:
privatestring _nombre;
Esta propiedad almacena el valor que deseamos proteger. Para interactuar con esta propiedad, creamos una pública:
publicstring Nombre
{get{return _nombre;}set{ _nombre =value.Trim();}}
Con la utilización de get y set, controlamos cómo se accede y se modifica el valor de _nombre, permitiendo por ejemplo, realizar una limpieza de espacios innecesarios con el método Trim().
Uso de métodos para modificar propiedades
El método set puede contener lógica adicional que modifique el valor antes de ser asignado a la propiedad privada. Este enfoque es beneficioso para validar o limpiar los datos que se reciben.
Propiedades solo de lectura
Otra forma de encapsular es a través de propiedades de solo lectura, las cuales únicamente tienen un get y ningún set:
Esta propiedad combinada solo permitirá la lectura del valor y no la asignación, encapsulando la lógica para combinar el nombre del superhéroe con su identidad secreta.
¿Por qué es importante el encapsulamiento?
El encapsulamiento nos ayuda a mantener un nivel de abstracción en nuestro código, protegiendo los datos internos de una clase y permitiendo que estos solo sean modificados a través de métodos definidos. Esto conduce a un código más seguro, modular y fácil de mantener. Además, al ocultar los detalles internos, se facilita la realización de cambios sin afectar a las clases que utilizan el objeto encapsulado.
¿Cuáles son los beneficios prácticos en un proyecto real?
Imaginemos un escenario donde los datos de entrada no son consistentes, como por ejemplo, el nombre de un superhéroe con espacios adicionales. Sin encapsulamiento, cada punto en el código donde se maneje este nombre deberá encargarse de su validación y limpieza. Encapsulando esta lógica, simplificamos el manejo al tener un único punto responsable de tratar estos valores, dejando el resto del código más limpio y enfocado en sus propias tareas.
El conocimiento y correcta aplicación del encapsulamiento marcarán un antes y un después en tu desarrollo profesional como programador. Es una herramienta que no solo ayuda a estructurar tu código sino que también comunica tus intenciones a otros desarrolladores que puedan trabajar en el mismo proyecto. Con cada concepto de POO que dominas, te acercas más al nivel de experto en el dinámico mundo del desarrollo de software. ¡Sigue adelante y no pares de aprender! El próximo paso en nuestro viaje es explorar el fascinante concepto de la herencia en POO. ¡Nos vemos en la próxima lección!
Se refiere a la idea de ocultar los detalles internos de un objeto y proporcionar una interfaz pública bien definida para interactuar con él.
El encapsulamiento permite controlar el acceso a los atributos y métodos de un objeto, lo que ayuda a mantener la integridad de los datos y facilita la gestión y el mantenimiento del código.
En el encapsulamiento, los atributos de un objeto se declaran como privados, lo que significa que solo pueden accederse y modificarse desde dentro de la propia clase a la que pertenece el objeto.
Para permitir que otros objetos interactúen con estos atributos, se proporcionan métodos públicos, también conocidos como métodos de acceso o getters y setters, que permiten obtener y establecer los valores de los atributos de manera controlada.
Los beneficios del encapsulamiento son:
Control de acceso: Se puede especificar quién tiene acceso a los datos y quién no. Esto ayuda a prevenir modificaciones no deseadas o inconsistentes en los datos.
Ocultamiento de detalles internos: Los detalles de implementación de una clase se mantienen ocultos, lo que facilita el cambio de la implementación sin afectar a los objetos que la utilizan.
Facilita la mantenibilidad: Al tener una interfaz pública bien definida, es más fácil identificar y corregir problemas en el código, ya que se sabe dónde se realizan las interacciones con el objeto.
En C# el encapsulamiento se logra utilizando modificadores de acceso como "<u>private</u>", "<u>public</u>" y "<u>protected</u>" para controlar el acceso a los atributos y métodos de una clase.
<u>Fuente: Chat GPT</u>
Microsoft Define "Encapsulación" como
ocultar el estado interno y la funcionalidad de un objeto y permitir solo el acceso a través de un conjunto público de funciones.
Gran ejemplo en la clase con los get; y set;
La encapsulación en programación, especialmente en lenguajes como C#, se refiere a la práctica de ocultar los detalles internos de una clase y proporcionar una interfaz pública para interactuar con la clase. Esto se logra utilizando modificadores de acceso como private, protected, public, entre otros, para controlar el acceso a los miembros de la clase (campos y métodos). Aquí tienes un ejemplo sencillo en C# que ilustra la encapsulación:
using System;publicclassPersona{// Campos privados (encapsulados)private string nombre;private int edad;// ConstructorpublicPersona(string nombre, int edad){this.nombre= nombre;this.edad= edad;}// Propiedades públicas para acceder a los campos privadospublic string Nombre{ get {return nombre;} set { nombre = value;}}public int Edad{ get {return edad;} set
{if(value >=0){ edad = value;}else{Console.WriteLine("La edad no puede ser un número negativo.");}}}// Método públicopublicvoidPresentarse(){Console.WriteLine($"Hola, soy {nombre} y tengo {edad} años.");}}classProgram{staticvoidMain(){// Crear una instancia de la clase PersonaPersona persona =newPersona("Juan",30);// Acceder a las propiedades públicas y llamar al método públicoConsole.WriteLine($"Nombre: {persona.Nombre}");Console.WriteLine($"Edad: {persona.Edad}"); persona.Presentarse();// Intentar establecer una edad negativa (esto mostrará el mensaje de error) persona.Edad=-5;// Cambiar la edad válida persona.Edad=35;// Mostrar la nueva edadConsole.WriteLine($"Nueva Edad: {persona.Edad}");}}
En este ejemplo, la clase Persona encapsula los campos nombre y edad al hacerlos privados y proporciona propiedades públicas (Nombre y Edad) para acceder a estos campos de manera controlada. También tiene un método público llamado Presentarse que permite mostrar información sobre la persona. Esto es un ejemplo básico de encapsulación en C#.
Hasta al momento me ha gustado el curso :)
Así llevo mi clase persona, con validaciones.
use el string.IsNullOrWhiteSpace:
Este método verifica si una cadena es nula (null), una cadena vacía ("") o si contiene solo espacios en blanco.
Devuelve true si la cadena es nula, una cadena vacía o contiene solo espacios en blanco.
Devuelve false si la cadena contiene al menos un carácter distinto de un espacio en blanco.
Gracias por compartir tu codigo, me gusto el ejemplo
Si una propiedad solo tiene get , es igual que un readonly?
Una propiedad solo con get es de solo lectura, al igual que una propiedad 'readonly', pero difieren en que la primera permite asignación en cualquier momento dentro de la clase, mientras que la segunda solo se asigna durante la declaración o en el constructor y su valor es constante después de la inicialización.
Simulamos un readonly encansulando solo el metodo para obtener datos es correcto.
Es la primera ves que me encuentro con la declaración de una propiedad una privada precedida de un guion bajo y el nombre de la variable con Pascal Case y posterior a ello una pública con el mismo nombre (siguiendo la regla anterior pero sin el guion bajo), con los métodos get y set.
Entiendo que lo anterior responde a las reglas de codificación de cada lenguaje, sin embargo, más allá de la forma como han escrito los atributos de la clase, me queda la duda si, ¿Es así como se declaran los atributos a nivel profesional (uno publico y otro privado) o fue netamente para la metodología académica?
Hola, tengo exactamente la misma duda.
Creoq ue hubiese sido chido mostrar como funciona el Get y el Set con métodos ya que ese permite explicar un poquito el tema de por qué se denomina así y como funciona el tema del scope en este caso. Pese a eso, la explicación de la propiedad pública y privada del Nombre en conjunto con el set y el get es brillante!
Muy buena clase!
Comparto mi ejercicio donde unifiqué todos los conceptos vistos hasta el momento en clase: Encapsulamiento, Métodos y Enumeraciones, aplicándolos al personaje de Deadpool
using System;using System.Collections.Generic;using System.Text;
namespace EjercicioPOO
{// 1 Definimos los noveles de poder con un ENUM enumNivelPoder{ NivelUno, NivelDos, NivelTres
}// 2 Clase para representar un SuperPoder class SuperPoder
{ public string Nombre { get; set;} public string Descripcion { get; set;} public NivelPoder Nivel { get; set;}}// 3 Clase Principal SuperHeroe class SuperHeroe
{//Campos Pirvados (el coraozn del encapsulamiento) private string _Nombre; private string _IdentidadSecreta; public Guid Id { get; set;}//Propiedad con validacion (Trim) public string Nombre
{ get => _Nombre; set => _Nombre = value.Trim();}// Propiedad encapsulada public string IdentidadSecreta
{ get => _IdentidadSecreta; set => _IdentidadSecreta = value;} public string Ciudad { get; set;} public List<SuperPoder> SuperPoderes {get; set;} public bool PuedeVolar { get; set;}//Metodo sin Retorno (void): Realiza una Accion Inmediata public voidRealizarSaludo(){ Console.WriteLine($"{Nombre} dice: '¡Chimichangas! soy {IdentidadSecreta}... digo, ¡{Nombre}!'");}//Metodo con Retorno (String): Procesa datos y devuelve una cadena usando StringBuilder public string UsarSuperpoderes(){ StringBuilder sb = new StringBuilder(); sb.AppendLine($"--- REPORTE DE ACCION: {Nombre} ---");foreach(var poder in SuperPoderes){ sb.AppendLine($"> Activando {poder.Nombre}: {poder.Descripcion} (Nivel: {poder.Nivel})");}return sb.ToString();}}// 4 Clase Program: El orquestador del sistema class Program
{staticvoidMain(string[] args){//Creamos los Poderes de Deadpool como objetos de la clase SuperPoder var regeneracion = new SuperPoder
{ Nombre ="Factor de Curacion", Descripcion ="Regeneracion Celular Acelerada ante Caulquier Daño.", Nivel = NivelPoder.NivelTres
}; var Katanas = new SuperPoder
{ Nombre ="Maestro de Armas", Descripcion ="Uso experto de Katanas dobles y punteria perfecta", Nivel = NivelPoder.NivelDos
};//Instanciamos nuestro SuperHeroe var deadpool = new SuperHeroe(); deadpool.Id = Guid.NewGuid(); deadpool.Nombre ="Deadpool "; deadpool.IdentidadSecreta ="Wade Wilson"; deadpool.Ciudad ="Nueva York"; deadpool.PuedeVolar = false;//Asignamos la Lista de Poderes deadpool.SuperPoderes = new List<SuperPoder>{ regeneracion, Katanas };// --- EJECUCION DE COMPORTAMIENTOS --- //Llamada al metodo void deadpool.RealizarSaludo(); Console.WriteLine();// Llamada al metodo con retorno // Almacenamos el string resultante en una variable y luego lo imprimimos string reporteCombate = deadpool.UsarSuperpoderes(); Console.WriteLine(reporteCombate);// Evitamos que la consola se cierre automaticamente Console.WriteLine("Presiona cualquier tecla para finalizar el ejercicio..."); Console.ReadKey();}}}
Me parece que llamar una variable _Nombre y otro Nombre puede llegar a confundir al tratarse de dos variables que en síntesis es lo mismo, yo me identifico más con esta forma:
private string identidadSecreta;
public string IdentidadSecreta
{
get { return identidadSecreta; }
set { identidadSecreta = value; }
}
El encapsulamiento es un principio de programación orientada a objetos que restringe el acceso a ciertos componentes de un objeto, ocultando su estado interno. Esto se logra mediante la creación de propiedades y métodos privados y públicos.
Ejemplo de uso en C#:
classSuperheroe{privatestring _nombre;publicstring Nombre {get{return _nombre;}set{ _nombre =value.Trim();}// Elimina espacios en blanco}}
En este ejemplo, _nombre es privado y no puede ser accedido directamente desde fuera de la clase. La propiedad Nombre permite obtener y establecer su valor, asegurando que siempre esté limpio de espacios adicionales.
Una buena practica es que los nombre empiecen en Mayúsculas y que este sea seguido por minúsculas, esta es la solución que nos propone c#:
el ejemplo no fue la mejor opcion, era mejor hacer ejemplos reales
Para entender completamente el concepto de encapsulamiento en la programación orientada a objetos, hay algunos conceptos adicionales que podrían ser útiles:
Modificadores de Acceso: En C#, los modificadores de acceso como public, private, protected y internal controlan la visibilidad de las propiedades y métodos de una clase. Por ejemplo, al declarar una variable como private, solo los métodos dentro de la misma clase pueden acceder a esa variable, lo que ayuda a encapsular y ocultar los detalles internos de la implementación.
Propiedades y Métodos Getters y Setters: En muchos lenguajes de programación orientados a objetos, incluido C#, se utilizan métodos de acceso (getters) y de modificación (setters) para interactuar con las propiedades de un objeto. Esto permite un control más preciso sobre cómo se acceden y modifican los datos internos de un objeto, lo que facilita el encapsulamiento.
Encapsulamiento de Datos: El encapsulamiento no solo se refiere a ocultar los detalles de implementación de una clase, sino también a garantizar que los datos se manejen de manera segura y coherente. Esto se logra mediante el uso de métodos de acceso controlado, validaciones de datos y la aplicación de reglas de negocio dentro de la clase.
Mantenimiento de la Invariabilidad: El encapsulamiento también implica mantener la invariabilidad de los objetos, es decir, garantizar que el estado interno de un objeto se mantenga consistente y válido en todo momento. Esto se logra mediante la restricción del acceso directo a los datos internos y la realización de operaciones de validación en métodos específicos.
fuente chatgpt
La encapsulación se usa cuando queremos hacer una transformación de nuestras propiedades, o cuando queremos crear nuevas variables a partir de una de nuestras propiedades
Beneficios del Encapsulamiento:
Evita la manipulación incorrecta de datos por parte del usuario.
Mejora la legibilidad del código al ocultar detalles de implementación.
Facilita la adición de comportamientos específicos en nuevas propiedades.
private string _nombreSuperHeroe;public string nombreSuperHeroe { get {return _nombreSuperHeroe;} set { _nombreSuperHeroe = value.Trim();}}