Claude
Skills
Sign in
Back

oop-encapsulation

Included with Lifetime
$97 forever

Use when applying encapsulation and information hiding principles in object-oriented design. Use when controlling access to object state and behavior.

Design

What this skill does


# OOP Encapsulation

Master encapsulation and information hiding to create robust, maintainable object-oriented systems. This skill focuses on controlling access to object internals and exposing well-defined interfaces.

## Understanding Encapsulation

Encapsulation is the bundling of data and methods that operate on that data within a single unit, while restricting direct access to some of the object's components. This principle protects object integrity and reduces coupling.

### Java Encapsulation

```java
// Strong encapsulation with validation
public class BankAccount {
    private String accountNumber;
    private BigDecimal balance;
    private final List<Transaction> transactions;

    public BankAccount(String accountNumber, BigDecimal initialBalance) {
        if (accountNumber == null || accountNumber.isEmpty()) {
            throw new IllegalArgumentException("Account number required");
        }
        if (initialBalance.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Initial balance cannot be negative");
        }

        this.accountNumber = accountNumber;
        this.balance = initialBalance;
        this.transactions = new ArrayList<>();
    }

    // Read-only access to account number
    public String getAccountNumber() {
        return accountNumber;
    }

    // Read-only access to balance
    public BigDecimal getBalance() {
        return balance;
    }

    // Defensive copy for collection
    public List<Transaction> getTransactions() {
        return Collections.unmodifiableList(transactions);
    }

    // Controlled mutation with validation
    public void deposit(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("Deposit amount must be positive");
        }

        balance = balance.add(amount);
        transactions.add(new Transaction(TransactionType.DEPOSIT, amount));
    }

    // Controlled mutation with business logic
    public void withdraw(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("Withdrawal amount must be positive");
        }
        if (amount.compareTo(balance) > 0) {
            throw new InsufficientFundsException("Insufficient balance");
        }

        balance = balance.subtract(amount);
        transactions.add(new Transaction(TransactionType.WITHDRAWAL, amount));
    }
}
```

### Python Encapsulation

```python
class Employee:
    """Employee with encapsulated salary information."""

    def __init__(self, name: str, salary: float, department: str):
        if not name:
            raise ValueError("Name is required")
        if salary < 0:
            raise ValueError("Salary cannot be negative")

        self._name = name  # Protected attribute
        self.__salary = salary  # Private attribute (name mangling)
        self._department = department
        self.__performance_rating = 0.0

    @property
    def name(self) -> str:
        """Read-only access to name."""
        return self._name

    @property
    def department(self) -> str:
        """Read-only access to department."""
        return self._department

    @property
    def salary(self) -> float:
        """Controlled access to salary."""
        return self.__salary

    @salary.setter
    def salary(self, value: float) -> None:
        """Controlled mutation with validation."""
        if value < 0:
            raise ValueError("Salary cannot be negative")
        if value < self.__salary * 0.9:
            raise ValueError("Salary cannot decrease by more than 10%")

        self.__salary = value

    @property
    def performance_rating(self) -> float:
        """Read-only access to performance rating."""
        return self.__performance_rating

    def update_performance(self, rating: float) -> None:
        """Controlled update with validation and side effects."""
        if not 0 <= rating <= 5:
            raise ValueError("Rating must be between 0 and 5")

        self.__performance_rating = rating

        # Business logic: automatic raise for high performers
        if rating >= 4.5:
            self.__salary *= 1.10

    def give_raise(self, percentage: float) -> None:
        """Apply percentage raise with validation."""
        if percentage < 0:
            raise ValueError("Raise percentage cannot be negative")
        if percentage > 20:
            raise ValueError("Single raise cannot exceed 20%")

        self.__salary *= (1 + percentage / 100)

    def __repr__(self) -> str:
        return f"Employee(name={self._name}, department={self._department})"
```

### TypeScript Encapsulation

```typescript
// Class-based encapsulation with private fields
class UserAccount {
  readonly #id: string;
  #username: string;
  #email: string;
  #passwordHash: string;
  #lastLoginAt: Date | null = null;
  #failedLoginAttempts = 0;
  #isLocked = false;

  constructor(username: string, email: string, passwordHash: string) {
    if (!username || username.length < 3) {
      throw new Error("Username must be at least 3 characters");
    }
    if (!this.isValidEmail(email)) {
      throw new Error("Invalid email format");
    }

    this.#id = crypto.randomUUID();
    this.#username = username;
    this.#email = email;
    this.#passwordHash = passwordHash;
  }

  // Read-only access
  get id(): string {
    return this.#id;
  }

  get username(): string {
    return this.#username;
  }

  get email(): string {
    return this.#email;
  }

  get lastLoginAt(): Date | null {
    return this.#lastLoginAt;
  }

  get isLocked(): boolean {
    return this.#isLocked;
  }

  // Controlled mutation with validation
  updateEmail(newEmail: string): void {
    if (!this.isValidEmail(newEmail)) {
      throw new Error("Invalid email format");
    }
    this.#email = newEmail;
  }

  // Business logic encapsulated
  attemptLogin(password: string): boolean {
    if (this.#isLocked) {
      throw new Error("Account is locked");
    }

    if (this.verifyPassword(password)) {
      this.#lastLoginAt = new Date();
      this.#failedLoginAttempts = 0;
      return true;
    }

    this.#failedLoginAttempts++;
    if (this.#failedLoginAttempts >= 3) {
      this.#isLocked = true;
    }
    return false;
  }

  // Private helper methods
  private isValidEmail(email: string): boolean {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  }

  private verifyPassword(password: string): boolean {
    // Hash comparison logic
    return true; // Simplified
  }

  unlock(): void {
    this.#isLocked = false;
    this.#failedLoginAttempts = 0;
  }
}
```

### C# Encapsulation

```csharp
// Strong encapsulation with properties and backing fields
public class Product
{
    private readonly Guid _id;
    private string _name;
    private decimal _price;
    private int _stockQuantity;
    private readonly List<PriceHistory> _priceHistory;

    public Product(string name, decimal price, int initialStock)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("Product name is required", nameof(name));

        if (price <= 0)
            throw new ArgumentException("Price must be positive", nameof(price));

        if (initialStock < 0)
            throw new ArgumentException("Stock cannot be negative", nameof(initialStock));

        _id = Guid.NewGuid();
        _name = name;
        _price = price;
        _stockQuantity = initialStock;
        _priceHistory = new List<PriceHistory>
        {
            new PriceHistory(price, DateTime.UtcNow)
        };
    }

    // Read-only property
    public Guid Id => _id;

    // Property with validation
    public string Name
    {
        get => _name;
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("Product name is required");
            _name = value;
        }
    }

    // Property with side effects
    public decimal

Related in Design