Claude
Skills
Sign in
Back

oop-inheritance-composition

Included with Lifetime
$97 forever

Use when deciding between inheritance and composition in object-oriented design. Use when creating class hierarchies or composing objects from smaller components.

Design

What this skill does


# OOP Inheritance and Composition

Master inheritance and composition to build flexible, maintainable object-oriented systems. This skill focuses on understanding when to use inheritance versus composition and how to apply each effectively.

## Inheritance Fundamentals

### Basic Inheritance in Java

```java
// Base class with common behavior
public abstract class Vehicle {
    private String brand;
    private String model;
    private int year;
    protected double currentSpeed;

    protected Vehicle(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.currentSpeed = 0.0;
    }

    // Template method pattern
    public final void start() {
        performSafetyCheck();
        startEngine();
        System.out.println(brand + " " + model + " started");
    }

    // Hook method for subclasses
    protected void performSafetyCheck() {
        System.out.println("Performing basic safety check");
    }

    // Abstract method - must be implemented
    protected abstract void startEngine();

    public void accelerate(double speed) {
        currentSpeed += speed;
        System.out.println("Current speed: " + currentSpeed);
    }

    public void brake(double reduction) {
        currentSpeed = Math.max(0, currentSpeed - reduction);
        System.out.println("Current speed: " + currentSpeed);
    }

    // Getters
    public String getBrand() { return brand; }
    public String getModel() { return model; }
    public int getYear() { return year; }
    public double getCurrentSpeed() { return currentSpeed; }
}

// Concrete implementation
public class Car extends Vehicle {
    private int numberOfDoors;
    private boolean isSunroofOpen;

    public Car(String brand, String model, int year, int numberOfDoors) {
        super(brand, model, year);
        this.numberOfDoors = numberOfDoors;
        this.isSunroofOpen = false;
    }

    @Override
    protected void startEngine() {
        System.out.println("Car engine started with ignition");
    }

    @Override
    protected void performSafetyCheck() {
        super.performSafetyCheck();
        System.out.println("Checking doors are closed");
        System.out.println("Checking seatbelts");
    }

    public void openSunroof() {
        if (currentSpeed == 0) {
            isSunroofOpen = true;
            System.out.println("Sunroof opened");
        } else {
            System.out.println("Stop the car before opening sunroof");
        }
    }

    public int getNumberOfDoors() {
        return numberOfDoors;
    }
}

// Another concrete implementation
public class Motorcycle extends Vehicle {
    private boolean hasWindshield;

    public Motorcycle(String brand, String model, int year, boolean hasWindshield) {
        super(brand, model, year);
        this.hasWindshield = hasWindshield;
    }

    @Override
    protected void startEngine() {
        System.out.println("Motorcycle engine started with kick/button");
    }

    @Override
    public void accelerate(double speed) {
        // Override to add motorcycle-specific behavior
        if (currentSpeed + speed > 200) {
            System.out.println("Warning: Maximum safe speed exceeded!");
        }
        super.accelerate(speed);
    }

    public boolean hasWindshield() {
        return hasWindshield;
    }
}
```

### Inheritance in Python

```python
from abc import ABC, abstractmethod
from typing import List, Optional
from datetime import datetime

class Employee(ABC):
    """Abstract base class for all employees."""

    def __init__(self, employee_id: str, name: str, email: str, hire_date: datetime):
        self._employee_id = employee_id
        self._name = name
        self._email = email
        self._hire_date = hire_date
        self._is_active = True

    @property
    def employee_id(self) -> str:
        return self._employee_id

    @property
    def name(self) -> str:
        return self._name

    @property
    def email(self) -> str:
        return self._email

    @property
    def hire_date(self) -> datetime:
        return self._hire_date

    @property
    def years_of_service(self) -> int:
        return (datetime.now() - self._hire_date).days // 365

    # Template method
    def process_payroll(self) -> float:
        """Process payroll - template method."""
        if not self._is_active:
            raise ValueError("Cannot process payroll for inactive employee")

        base_pay = self.calculate_pay()
        bonus = self.calculate_bonus()
        deductions = self.calculate_deductions()

        total_pay = base_pay + bonus - deductions
        self.record_payment(total_pay)
        return total_pay

    # Abstract methods - must be implemented by subclasses
    @abstractmethod
    def calculate_pay(self) -> float:
        """Calculate base pay."""
        pass

    # Hook methods with default implementation
    def calculate_bonus(self) -> float:
        """Calculate bonus - can be overridden."""
        return 0.0

    def calculate_deductions(self) -> float:
        """Calculate deductions - can be overridden."""
        return 0.0

    def record_payment(self, amount: float) -> None:
        """Record payment."""
        print(f"Recording payment of ${amount:.2f} for {self._name}")

    def deactivate(self) -> None:
        """Deactivate employee."""
        self._is_active = False


class SalariedEmployee(Employee):
    """Employee paid a fixed salary."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        annual_salary: float
    ):
        super().__init__(employee_id, name, email, hire_date)
        self._annual_salary = annual_salary

    def calculate_pay(self) -> float:
        """Calculate monthly salary."""
        return self._annual_salary / 12

    def calculate_bonus(self) -> float:
        """Annual bonus based on years of service."""
        return self._annual_salary * 0.01 * self.years_of_service


class HourlyEmployee(Employee):
    """Employee paid by the hour."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        hourly_rate: float
    ):
        super().__init__(employee_id, name, email, hire_date)
        self._hourly_rate = hourly_rate
        self._hours_worked = 0.0

    def log_hours(self, hours: float) -> None:
        """Log hours worked this period."""
        if hours < 0:
            raise ValueError("Hours cannot be negative")
        self._hours_worked += hours

    def calculate_pay(self) -> float:
        """Calculate pay based on hours worked."""
        regular_hours = min(self._hours_worked, 40)
        overtime_hours = max(0, self._hours_worked - 40)

        regular_pay = regular_hours * self._hourly_rate
        overtime_pay = overtime_hours * self._hourly_rate * 1.5

        return regular_pay + overtime_pay

    def record_payment(self, amount: float) -> None:
        """Record payment and reset hours."""
        super().record_payment(amount)
        self._hours_worked = 0.0


class CommissionEmployee(SalariedEmployee):
    """Employee with base salary plus commission."""

    def __init__(
        self,
        employee_id: str,
        name: str,
        email: str,
        hire_date: datetime,
        annual_salary: float,
        commission_rate: float
    ):
        super().__init__(employee_id, name, email, hire_date, annual_salary)
        self._commission_rate = commission_rate
        self._sales_this_period = 0.0

    def record_sale(self, amount: float) -> None:
        """Record a sale for commission calculation."""
        if amount <= 0:
            raise ValueError("Sale amount must be positive")
        self._sales_this_period += amount

    def calculate_pay(self) -> float:
        """Calculate base salary plus commission."""
        base = super().calculate_pay()
        commission = self._sale

Related in Design