Modificadores de acceso
Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy — lección 31 de 70.
Los modificadores de acceso controlan quién puede ver y utilizar los miembros de su clase. Son la base del encapsulamiento, uno de los principios fundamentales de la POO. Al restringir el acceso, protege sus datos y crea límites claros en su código.
C# proporciona cuatro modificadores de acceso principales:
public class BankAccount
{
public string AccountHolder; // Accesible desde cualquier lugar
private decimal balance; // Solo dentro de esta clase
protected string accountType; // Esta clase y clases derivadas
internal int branchCode; // Dentro del mismo ensamblado
}Los miembros public son accesibles desde cualquier código.
Los miembros private solo pueden ser accedidos dentro de la misma clase; este es el más restrictivo y el predeterminado para los miembros de la clase.
protected permite el acceso desde la propia clase y cualquier clase que herede de ella.
internal restringe el acceso al código dentro del mismo ensamblado (proyecto).
Cuando no se especifica ningún modificador, los miembros de la clase por defecto son private:
class Example
{
int secret; // privado por defecto
}Elegir el nivel de acceso adecuado consiste en exponer solo lo que es necesario. Comienza con private y aumenta la visibilidad solo cuando tengas una razón clara. Esto evita que otro código dependa de detalles de implementación que podrías querer cambiar más adelante.
Desafío
FácilVamos a construir un sistema de perfil de usuario seguro que demuestre cómo los modificadores de acceso protegen los datos sensibles mientras exponen solo lo necesario. Crearás una clase donde diferentes piezas de información tengan diferentes niveles de visibilidad basados en quién debería poder acceder a ellas.
Organizarás tu código en tres archivos:
UserProfile.cs: Crea una claseUserProfileen el espacio de nombresSecurityque gestione la información del usuario con los niveles de acceso adecuados. El perfil debe tener:- Una propiedad
publicUsername(string) - cualquiera puede ver el nombre de usuario - Un campo
privatepassword(string) - solo la propia clase debe acceder a esto - Un campo
protectedemail(string) - la clase y sus clases derivadas pueden acceder a esto - Un campo
internaluserId(int) - accesible dentro del mismo ensamblado
publicllamadoGetPublicInfo()que devuelva"User: {Username}". Añade otro métodopublicllamadoValidatePassword(string input)que devuelvatruesi la entrada coincide con la contraseña privada, yfalseen caso contrario.- Una propiedad
AdminProfile.cs: Crea una claseAdminProfileen el espacio de nombresSecurityque herede deUserProfile. Esta clase demuestra cómo los miembrosprotectedse vuelven accesibles en las clases derivadas. El constructor debe aceptar los mismos cuatro parámetros y pasarlos al constructor base. Añade un métodopublicllamadoGetAdminInfo()que devuelva"Admin: {Username}, Email: {email}"- ¡observa que puedes acceder al campo protegidoemailaquí!Program.cs: En tu archivo principal, crea unUserProfiley unAdminProfileutilizando los valores de entrada. Demuestra los niveles de acceso llamando a los métodos públicos disponibles y accediendo al campo interno directamente (ya que estás en el mismo ensamblado). Muestra qué información puede revelar cada tipo de usuario.
Recibirás cinco entradas:
- Nombre de usuario (Username)
- Contraseña (Password)
- Correo electrónico (Email)
- ID de usuario (User ID - entero)
- Intento de contraseña para validar
Imprime la salida en este formato:
Regular User:
{GetPublicInfo() result}
Internal ID: {userId}
Password valid: {ValidatePassword result}
Admin User:
{GetAdminInfo() result}Por ejemplo, si las entradas son alice, secret123, alice@email.com, 1001, y secret123, la salida debería ser:
Regular User:
User: alice
Internal ID: 1001
Password valid: True
Admin User:
Admin: alice, Email: alice@email.comObserva cómo la contraseña permanece completamente oculta - solo puedes validarla, nunca recuperarla. El correo electrónico está protegido, por lo que solo el AdminProfile (una clase derivada) puede exponerlo. El userId interno es accesible desde tu archivo principal porque está en el mismo ensamblado. ¡Esto es la encapsulación en acción!
Hoja de referencia
Los modificadores de acceso controlan la visibilidad y accesibilidad de los miembros de la clase, formando la base del encapsulamiento en la POO.
C# proporciona cuatro modificadores de acceso principales:
public class BankAccount
{
public string AccountHolder; // Accesible desde cualquier lugar
private decimal balance; // Solo dentro de esta clase
protected string accountType; // Esta clase y clases derivadas
internal int branchCode; // Dentro del mismo ensamblado
}public: accesible desde cualquier código
private: solo accesible dentro de la misma clase (el más restrictivo, predeterminado para los miembros de la clase)
protected: accesible desde la propia clase y cualquier clase derivada
internal: accesible solo dentro del mismo ensamblado (proyecto)
Cuando no se especifica ningún modificador, los miembros de la clase son private por defecto:
class Example
{
int secret; // private por defecto
}Mejor práctica: comience con private y solo aumente la visibilidad cuando sea necesario para evitar que el código externo dependa de los detalles de implementación.
Pruébalo tú mismo
using System;
using Security;
class Program
{
public static void Main(string[] args)
{
// Leer entradas
string username = Console.ReadLine();
string password = Console.ReadLine();
string email = Console.ReadLine();
int userId = Convert.ToInt32(Console.ReadLine());
string passwordAttempt = Console.ReadLine();
// TODO: Crear un objeto UserProfile con los valores de entrada
// TODO: Crear un objeto AdminProfile con los mismos valores de entrada
// TODO: Imprimir "Regular User:"
// TODO: Imprimir el resultado de GetPublicInfo()
// TODO: Imprimir "Internal ID: " seguido del campo userId (accesible porque es el mismo assembly)
// TODO: Imprimir "Password valid: " seguido del resultado de ValidatePassword()
// TODO: Imprimir "Admin User:"
// TODO: Imprimir el resultado de GetAdminInfo()
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantes