Encapsulation
Encapsulation är som att ha en säkerhetsvakt för din kod! Du bestämmer vad som får komma in, vad som får gå ut, och vad som ska vara hemligt. Som James Bond för dina variabler! 🕵️♂️
🎯 Efter denna artikel kommer du att:
- Förstå encapsulation konceptet - information hiding på svenska! 🙈
- Använda access modifiers - public, private, protected som en pro 🔑
- Skapa properties med getters/setters - controlled access patterns 🎛️
- Designa secure classes - protect your data like Fort Knox! 🏛️
🔒 Access Modifiers - Säkerhetsnivåer
🌟 Public - Öppen för alla
public class Restaurant
{
public string Name { get; set; } // Alla kan se och ändra
public string Address { get; set; } // Helt öppet
public void TakeOrder(string dish) // Alla kan beställa
{
Console.WriteLine($"🍽️ Order: {dish} received!");
}
public void ShowMenu() // Alla kan se menyn
{
Console.WriteLine("📋 Today's menu: Pizza, Pasta, Salad");
}
}
// Usage - anyone can access
Restaurant restaurant = new Restaurant();
restaurant.Name = "Mario's Pizza"; // ✅ OK - public
restaurant.TakeOrder("Pizza Margherita"); // ✅ OK - public method
🔒 Private - Strikt hemligt
public class ATM
{
// Private fields - bara denna klass kan använda
private decimal _totalCash = 100000;
private string _adminPin = "1337";
private List<string> _transactionLog = new();
public void WithdrawCash(decimal amount, string userPin)
{
if (ValidateTransaction(amount) && AuthenticateUser(userPin))
{
_totalCash -= amount; // ✅ Private field - OK from inside class
LogTransaction($"Withdrawal: {amount}"); // ✅ Private method - OK
Console.WriteLine($"💰 Dispensing {amount:C}");
}
else
{
Console.WriteLine("❌ Transaction denied!");
}
}
// Private methods - internal logic
private bool ValidateTransaction(decimal amount)
{
return amount > 0 && amount <= _totalCash && amount <= 5000;
}
private bool AuthenticateUser(string pin)
{
// In real life: check against database
return pin.Length == 4; // Simplified
}
private void LogTransaction(string transaction)
{
_transactionLog.Add($"{DateTime.Now}: {transaction}");
}
// Public method to get limited info
public string GetATMStatus()
{
return $"ATM operational. Cash available: {_totalCash > 1000}";
}
}
// Usage - limited access
ATM atm = new ATM();
atm.WithdrawCash(500, "1234"); // ✅ OK - public method
// atm._totalCash = 0; // ❌ Compilation error - private!
// atm.ValidateTransaction(100); // ❌ Compilation error - private method!
🔐 Protected - Bara familjen
public class Vehicle // Parent class
{
protected string _engineType = "V6"; // Bara family kan använda
protected int _maxSpeed = 120; // Children kan accessa
private string _chassisNumber = "ABC123"; // Bara Vehicle class
public void StartEngine()
{
Console.WriteLine($"🚗 Starting {_engineType} engine");
InitializeSystem(); // ✅ Protected method from same class
}
protected void InitializeSystem() // Children kan override/använda detta
{
Console.WriteLine("🔧 System initialized");
}
}
public class SportsCar : Vehicle // Child class
{
public void ActivateTurbo()
{
if (_maxSpeed > 200) // ✅ Protected field - OK from child
{
Console.WriteLine($"🚀 Turbo activated! Max speed: {_maxSpeed} km/h");
InitializeSystem(); // ✅ Protected method - OK from child
}
// Console.WriteLine(_chassisNumber); // ❌ Error - private field!
}
protected override void InitializeSystem() // Override protected method
{
base.InitializeSystem();
Console.WriteLine("🏎️ Sports car systems online!");
}
}
🎯 Hands-On Workshop: Smart Home System
using System;
using System.Collections.Generic;
using System.Linq;
public class SmartHome
{
// Private fields - internal state
private Dictionary<string, SmartDevice> _devices;
private string _ownerName;
private bool _securityEnabled;
private List<string> _securityLog;
// Public properties med validation
public string OwnerName
{
get => _ownerName;
set => _ownerName = !string.IsNullOrWhiteSpace(value) ? value : "Unknown Owner";
}
public bool SecurityEnabled
{
get => _securityEnabled;
set
{
if (_securityEnabled != value)
{
_securityEnabled = value;
LogSecurityEvent($"Security {(value ? "ENABLED" : "DISABLED")}");
NotifyAllDevices($"Security mode: {(value ? "ON" : "OFF")}");
}
}
}
// Read-only properties
public int DeviceCount => _devices.Count;
public string SystemStatus
{
get
{
var activeDevices = _devices.Values.Count(d => d.IsActive);
return $"🏠 {OwnerName}'s Home: {activeDevices}/{DeviceCount} devices active, Security: {(_securityEnabled ? "🔒" : "🔓")}";
}
}
public SmartHome(string ownerName)
{
OwnerName = ownerName; // Uses property validation
_devices = new Dictionary<string, SmartDevice>();
_securityLog = new List<string>();
_securityEnabled = false;
}
// Public methods - controlled interface
public void AddDevice(SmartDevice device)
{
if (device == null)
{
Console.WriteLine("❌ Cannot add null device");
return;
}
if (_devices.ContainsKey(device.Name))
{
Console.WriteLine($"⚠️ Device '{device.Name}' already exists");
return;
}
_devices[device.Name] = device;
device.SetHome(this); // Let device know which home it belongs to
Console.WriteLine($"✅ Added device: {device.Name}");
LogSecurityEvent($"Device added: {device.Name}");
}
public void ControlDevice(string deviceName, string command)
{
if (!_devices.ContainsKey(deviceName))
{
Console.WriteLine($"❌ Device '{deviceName}' not found");
return;
}
var device = _devices[deviceName];
device.ExecuteCommand(command);
LogSecurityEvent($"Command '{command}' sent to {deviceName}");
}
public void ShowDevices()
{
Console.WriteLine($"\n🏠 {SystemStatus}");
Console.WriteLine("📱 Devices:");
foreach (var device in _devices.Values)
{
Console.WriteLine($" {device.GetStatusDisplay()}");
}
}
public void ShowSecurityLog(int lastEntries = 5)
{
Console.WriteLine($"\n🛡️ Security Log (last {lastEntries} entries):");
var entries = _securityLog.TakeLast(lastEntries);
foreach (var entry in entries)
{
Console.WriteLine($" {entry}");
}
}
// Private methods - internal logic
private void LogSecurityEvent(string eventDescription)
{
var logEntry = $"[{DateTime.Now:HH:mm:ss}] {eventDescription}";
_securityLog.Add(logEntry);
}
private void NotifyAllDevices(string message)
{
foreach (var device in _devices.Values)
{
device.ReceiveNotification(message);
}
}
}
public abstract class SmartDevice
{
// Protected fields - family can access
protected string _name;
protected bool _isActive;
protected SmartHome _parentHome;
// Private fields - device secrets
private string _deviceId = Guid.NewGuid().ToString()[..8];
private DateTime _lastActivity = DateTime.Now;
// Public properties
public string Name => _name;
public bool IsActive => _isActive;
public string DeviceId => _deviceId; // Read-only exposure of private field
protected SmartDevice(string name)
{
_name = name ?? "Unknown Device";
_isActive = false;
}
// Public interface
public void SetHome(SmartHome home)
{
_parentHome = home;
}
public abstract void ExecuteCommand(string command);
public virtual string GetStatusDisplay()
{
var status = _isActive ? "🟢 ON" : "🔴 OFF";
return $"{status} {_name} (ID: {_deviceId})";
}
public virtual void ReceiveNotification(string message)
{
Console.WriteLine($"📢 {_name} received: {message}");
}
// Protected methods - children can use
protected void UpdateActivity()
{
_lastActivity = DateTime.Now;
}
protected void LogDeviceAction(string action)
{
Console.WriteLine($"📝 [{DateTime.Now:HH:mm:ss}] {_name}: {action}");
UpdateActivity();
}
}
public class SmartLight : SmartDevice
{
private int _brightness = 100;
private string _color = "white";
public int Brightness
{
get => _brightness;
private set => _brightness = Math.Max(0, Math.Min(100, value));
}
public string Color
{
get => _color;
private set => _color = value ?? "white";
}
public SmartLight(string name) : base(name) { }
public override void ExecuteCommand(string command)
{
var parts = command.ToLower().Split(' ');
switch (parts[0])
{
case "on":
_isActive = true;
LogDeviceAction("Light turned ON");
break;
case "off":
_isActive = false;
LogDeviceAction("Light turned OFF");
break;
case "brightness":
if (parts.Length > 1 && int.TryParse(parts[1], out int brightness))
{
Brightness = brightness;
LogDeviceAction($"Brightness set to {_brightness}%");
}
break;
case "color":
if (parts.Length > 1)
{
Color = parts[1];
LogDeviceAction($"Color changed to {_color}");
}
break;
default:
Console.WriteLine($"❌ Unknown command: {command}");
break;
}
}
public override string GetStatusDisplay()
{
var baseStatus = base.GetStatusDisplay();
if (_isActive)
return $"{baseStatus} - {_brightness}% {_color}";
return baseStatus;
}
}
public class SmartThermostat : SmartDevice
{
private double _currentTemp = 20.0;
private double _targetTemp = 22.0;
public double CurrentTemperature => _currentTemp;
public double TargetTemperature
{
get => _targetTemp;
set
{
if (value < 10 || value > 30)
{
Console.WriteLine("⚠️ Temperature must be between 10-30°C");
return;
}
_targetTemp = value;
LogDeviceAction($"Target temperature set to {_targetTemp}°C");
}
}
public SmartThermostat(string name) : base(name)
{
_isActive = true; // Thermostats are always active
}
public override void ExecuteCommand(string command)
{
var parts = command.ToLower().Split(' ');
switch (parts[0])
{
case "temp":
case "temperature":
if (parts.Length > 1 && double.TryParse(parts[1], out double temp))
{
TargetTemperature = temp;
}
break;
case "status":
var diff = _targetTemp - _currentTemp;
var status = Math.Abs(diff) < 0.5 ? "Perfect" :
diff > 0 ? $"Heating (+{diff:F1}°C)" :
$"Cooling ({diff:F1}°C too warm)";
Console.WriteLine($"🌡️ Current: {_currentTemp}°C, Target: {_targetTemp}°C - {status}");
break;
default:
Console.WriteLine($"❌ Unknown thermostat command: {command}");
break;
}
}
}
// Demo program
class Program
{
static void Main()
{
Console.WriteLine("🏠 SMART HOME SYSTEM DEMO 🏠");
Console.WriteLine("============================");
// Create smart home
var home = new SmartHome("Marcus Medina");
// Add devices
home.AddDevice(new SmartLight("Living Room Light"));
home.AddDevice(new SmartLight("Bedroom Light"));
home.AddDevice(new SmartThermostat("Main Thermostat"));
// Show initial status
home.ShowDevices();
Console.WriteLine("\n🎮 Controlling devices:");
// Control devices
home.ControlDevice("Living Room Light", "on");
home.ControlDevice("Living Room Light", "brightness 75");
home.ControlDevice("Living Room Light", "color blue");
home.ControlDevice("Bedroom Light", "on");
home.ControlDevice("Main Thermostat", "temperature 24");
home.ControlDevice("Main Thermostat", "status");
// Enable security
Console.WriteLine("\n🔒 Enabling security:");
home.SecurityEnabled = true;
// Show final status
home.ShowDevices();
home.ShowSecurityLog();
}
}
🔄 Encapsulation vs Other OOP Principles
Encapsulation + Inheritance
public class Vehicle
{
protected string _make; // Children can access
private string _vin; // Only Vehicle class
public string Make => _make; // Public getter
protected Vehicle(string make, string vin)
{
_make = make ?? "Unknown";
_vin = vin ?? GenerateVIN();
}
private string GenerateVIN() => Guid.NewGuid().ToString()[..17];
}
public class Car : Vehicle
{
public Car(string make, string vin) : base(make, vin)
{
// Can access _make (protected) but not _vin (private)
Console.WriteLine($"Created car: {_make}");
}
}
Encapsulation + Polymorphism
public abstract class Shape
{
protected double _area; // Calculated by children
public double Area => _area; // Read-only access
public abstract void CalculateArea(); // Each shape calculates differently
protected void ValidateDimension(double value, string dimensionName)
{
if (value <= 0)
throw new ArgumentException($"{dimensionName} must be positive");
}
}
public class Circle : Shape
{
private double _radius;
public double Radius
{
get => _radius;
set
{
ValidateDimension(value, "Radius"); // Use protected method
_radius = value;
CalculateArea(); // Recalculate when changed
}
}
public Circle(double radius)
{
Radius = radius; // Uses property validation
}
public override void CalculateArea()
{
_area = Math.PI * _radius * _radius;
}
}
💡 Marcus Encapsulation Wisdom
“Encapsulation är som att vara bouncer på en nattklubb - du kontrollerar vem som får komma in, vad de får göra, och vad som ska hållas hemligt! Good bouncers make good code!” 🕺💂
Real story: Första gången jag lät allt vara public (2001) för att “det var enklare”… tre månader senare hade någon annan utvecklare förstört min class genom att sätta balance = -999999. Sen dess: encapsulation EVERYWHERE! 🛡️
Pro tip: Start med allt private, sedan öppna upp bara det som BEHÖVER vara åtkomligt. Det är lättare att göra saker mer öppna än att stänga igen säkerhetshål senare! 🔐
Ready för Polymorphism och Interfaces? Encapsulation är fundamentet - nu blir det riktigt kraftfullt! 🎭