面向对象编程的继承与组合Skill oop-inheritance-composition

这个技能专注于面向对象编程中继承和组合的应用,用于设计类层次结构、组合对象以及实现设计模式如模板方法和策略模式。它提供多语言示例、最佳实践和常见陷阱,帮助构建灵活、可维护的软件系统。关键词:继承、组合、面向对象设计、类层次、代码重用、设计模式、软件架构、OOP。

架构设计 0 次安装 0 次浏览 更新于 3/25/2026

名称: oop-继承-组合 用户可调用: false 描述: 在面向对象设计中决定使用继承还是组合时使用。当创建类层次结构或从较小组件组合对象时使用。 允许的工具:

  • Bash
  • Read

OOP 继承与组合

掌握继承和组合以构建灵活、可维护的面向对象系统。此技能侧重于理解何时使用继承与组合以及如何有效应用每种方法。

继承基础

Java 中的基本继承

// 具有共同行为的基类
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;
    }

    // 模板方法模式
    public final void start() {
        performSafetyCheck();
        startEngine();
        System.out.println(brand + " " + model + " started");
    }

    // 子类的钩子方法
    protected void performSafetyCheck() {
        System.out.println("执行基本安全检查");
    }

    // 抽象方法 - 必须实现
    protected abstract void startEngine();

    public void accelerate(double speed) {
        currentSpeed += speed;
        System.out.println("当前速度: " + currentSpeed);
    }

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

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

// 具体实现
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("汽车引擎通过点火启动");
    }

    @Override
    protected void performSafetyCheck() {
        super.performSafetyCheck();
        System.out.println("检查车门是否关闭");
        System.out.println("检查安全带");
    }

    public void openSunroof() {
        if (currentSpeed == 0) {
            isSunroofOpen = true;
            System.out.println("天窗打开");
        } else {
            System.out.println("停车后再打开天窗");
        }
    }

    public int getNumberOfDoors() {
        return numberOfDoors;
    }
}

// 另一个具体实现
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("摩托车引擎通过踢/按钮启动");
    }

    @Override
    public void accelerate(double speed) {
        // 重写以添加摩托车特定行为
        if (currentSpeed + speed > 200) {
            System.out.println("警告: 超过最大安全速度!");
        }
        super.accelerate(speed);
    }

    public boolean hasWindshield() {
        return hasWindshield;
    }
}

Python 中的继承

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

class Employee(ABC):
    """所有员工的抽象基类。"""

    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

    # 模板方法
    def process_payroll(self) -> float:
        """处理工资单 - 模板方法。"""
        if not self._is_active:
            raise ValueError("无法为不活跃员工处理工资单")

        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

    # 抽象方法 - 必须由子类实现
    @abstractmethod
    def calculate_pay(self) -> float:
        """计算基本工资。"""
        pass

    # 带有默认实现的钩子方法
    def calculate_bonus(self) -> float:
        """计算奖金 - 可以重写。"""
        return 0.0

    def calculate_deductions(self) -> float:
        """计算扣除额 - 可以重写。"""
        return 0.0

    def record_payment(self, amount: float) -> None:
        """记录付款。"""
        print(f"为 {self._name} 记录 ${amount:.2f} 的付款")

    def deactivate(self) -> None:
        """停用员工。"""
        self._is_active = False


class SalariedEmployee(Employee):
    """按固定薪水支付的员工。"""

    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:
        """计算月薪。"""
        return self._annual_salary / 12

    def calculate_bonus(self) -> float:
        """基于服务年限的年度奖金。"""
        return self._annual_salary * 0.01 * self.years_of_service


class HourlyEmployee(Employee):
    """按小时支付的员工。"""

    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:
        """记录本周期工作小时数。"""
        if hours < 0:
            raise ValueError("小时数不能为负")
        self._hours_worked += hours

    def calculate_pay(self) -> float:
        """基于工作小时数计算工资。"""
        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:
        """记录付款并重置小时数。"""
        super().record_payment(amount)
        self._hours_worked = 0.0


class CommissionEmployee(SalariedEmployee):
    """带基本薪水和佣金的员工。"""

    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:
        """记录销售以计算佣金。"""
        if amount <= 0:
            raise ValueError("销售金额必须为正")
        self._sales_this_period += amount

    def calculate_pay(self) -> float:
        """计算基本薪水加佣金。"""
        base = super().calculate_pay()
        commission = self._sales_this_period * self._commission_rate
        return base + commission

    def record_payment(self, amount: float) -> None:
        """记录付款并重置销售。"""
        super().record_payment(amount)
        self._sales_this_period = 0.0

TypeScript 中的继承

// 抽象基类
abstract class Shape {
  protected readonly id: string;
  protected color: string;

  constructor(color: string) {
    this.id = crypto.randomUUID();
    this.color = color;
  }

  // 抽象方法
  abstract area(): number;
  abstract perimeter(): number;
  abstract draw(): void;

  // 具体方法
  getColor(): string {
    return this.color;
  }

  setColor(color: string): void {
    this.color = color;
  }

  describe(): string {
    return `${this.constructor.name} (${this.color}): 面积 = ${this.area().toFixed(2)}, 周长 = ${this.perimeter().toFixed(2)}`;
  }
}

// 具体实现
class Circle extends Shape {
  private radius: number;

  constructor(color: string, radius: number) {
    super(color);
    if (radius <= 0) {
      throw new Error("半径必须为正");
    }
    this.radius = radius;
  }

  area(): number {
    return Math.PI * this.radius ** 2;
  }

  perimeter(): number {
    return 2 * Math.PI * this.radius;
  }

  draw(): void {
    console.log(`绘制一个 ${this.color} 的圆形,半径为 ${this.radius}`);
  }

  getRadius(): number {
    return this.radius;
  }
}

class Rectangle extends Shape {
  private width: number;
  private height: number;

  constructor(color: string, width: number, height: number) {
    super(color);
    if (width <= 0 || height <= 0) {
      throw new Error("尺寸必须为正");
    }
    this.width = width;
    this.height = height;
  }

  area(): number {
    return this.width * this.height;
  }

  perimeter(): number {
    return 2 * (this.width + this.height);
  }

  draw(): void {
    console.log(`绘制一个 ${this.color} 的矩形 ${this.width}x${this.height}`);
  }

  isSquare(): boolean {
    return this.width === this.height;
  }
}

class Triangle extends Shape {
  private sideA: number;
  private sideB: number;
  private sideC: number;

  constructor(color: string, sideA: number, sideB: number, sideC: number) {
    super(color);
    if (!this.isValidTriangle(sideA, sideB, sideC)) {
      throw new Error("无效的三角形尺寸");
    }
    this.sideA = sideA;
    this.sideB = sideB;
    this.sideC = sideC;
  }

  private isValidTriangle(a: number, b: number, c: number): boolean {
    return a + b > c && b + c > a && a + c > b;
  }

  area(): number {
    // 海伦公式
    const s = this.perimeter() / 2;
    return Math.sqrt(s * (s - this.sideA) * (s - this.sideB) * (s - this.sideC));
  }

  perimeter(): number {
    return this.sideA + this.sideB + this.sideC;
  }

  draw(): void {
    console.log(`绘制一个 ${this.color} 的三角形`);
  }
}

组合优先于继承

Java 中的组合

// 组件接口
interface Engine {
    void start();
    void stop();
    int getHorsepower();
}

interface Transmission {
    void shiftUp();
    void shiftDown();
    String getType();
}

interface GPS {
    void navigate(String destination);
    String getCurrentLocation();
}

// 具体组件实现
class V6Engine implements Engine {
    private final int horsepower;
    private boolean running;

    public V6Engine(int horsepower) {
        this.horsepower = horsepower;
        this.running = false;
    }

    @Override
    public void start() {
        running = true;
        System.out.println("V6 引擎启动");
    }

    @Override
    public void stop() {
        running = false;
        System.out.println("V6 引擎停止");
    }

    @Override
    public int getHorsepower() {
        return horsepower;
    }
}

class ElectricEngine implements Engine {
    private final int horsepower;
    private boolean running;
    private int batteryLevel;

    public ElectricEngine(int horsepower) {
        this.horsepower = horsepower;
        this.batteryLevel = 100;
        this.running = false;
    }

    @Override
    public void start() {
        if (batteryLevel > 0) {
            running = true;
            System.out.println("电动引擎静音启动");
        } else {
            System.out.println("电池耗尽!");
        }
    }

    @Override
    public void stop() {
        running = false;
        System.out.println("电动引擎停止");
    }

    @Override
    public int getHorsepower() {
        return horsepower;
    }

    public int getBatteryLevel() {
        return batteryLevel;
    }
}

class AutomaticTransmission implements Transmission {
    private int currentGear;

    public AutomaticTransmission() {
        this.currentGear = 1;
    }

    @Override
    public void shiftUp() {
        if (currentGear < 8) {
            currentGear++;
            System.out.println("自动切换到齿轮 " + currentGear);
        }
    }

    @Override
    public void shiftDown() {
        if (currentGear > 1) {
            currentGear--;
            System.out.println("自动切换到齿轮 " + currentGear);
        }
    }

    @Override
    public String getType() {
        return "自动";
    }
}

class ManualTransmission implements Transmission {
    private int currentGear;

    public ManualTransmission() {
        this.currentGear = 1;
    }

    @Override
    public void shiftUp() {
        if (currentGear < 6) {
            currentGear++;
            System.out.println("手动切换到齿轮 " + currentGear);
        }
    }

    @Override
    public void shiftDown() {
        if (currentGear > 1) {
            currentGear--;
            System.out.println("手动切换到齿轮 " + currentGear);
        }
    }

    @Override
    public String getType() {
        return "手动";
    }
}

// 组合的汽车类
public class ComposedCar {
    private final Engine engine;
    private final Transmission transmission;
    private final GPS gps;  // 可选组件
    private final String brand;
    private final String model;

    // 用于灵活构建的建造者
    public static class Builder {
        private Engine engine;
        private Transmission transmission;
        private GPS gps;
        private String brand;
        private String model;

        public Builder brand(String brand) {
            this.brand = brand;
            return this;
        }

        public Builder model(String model) {
            this.model = model;
            return this;
        }

        public Builder engine(Engine engine) {
            this.engine = engine;
            return this;
        }

        public Builder transmission(Transmission transmission) {
            this.transmission = transmission;
            return this;
        }

        public Builder gps(GPS gps) {
            this.gps = gps;
            return this;
        }

        public ComposedCar build() {
            if (engine == null || transmission == null) {
                throw new IllegalStateException("需要引擎和变速器");
            }
            return new ComposedCar(this);
        }
    }

    private ComposedCar(Builder builder) {
        this.engine = builder.engine;
        this.transmission = builder.transmission;
        this.gps = builder.gps;
        this.brand = builder.brand;
        this.model = builder.model;
    }

    // 委托给组件
    public void start() {
        engine.start();
        System.out.println(brand + " " + model + " 准备驾驶");
    }

    public void stop() {
        engine.stop();
    }

    public void shiftUp() {
        transmission.shiftUp();
    }

    public void shiftDown() {
        transmission.shiftDown();
    }

    public void navigateTo(String destination) {
        if (gps != null) {
            gps.navigate(destination);
        } else {
            System.out.println("GPS 不可用");
        }
    }

    public String getSpecs() {
        return String.format("%s %s - %d HP %s 变速器",
            brand, model, engine.getHorsepower(), transmission.getType());
    }
}

// 使用
ComposedCar sportsCar = new ComposedCar.Builder()
    .brand("保时捷")
    .model("911")
    .engine(new V6Engine(450))
    .transmission(new ManualTransmission())
    .build();

ComposedCar electricCar = new ComposedCar.Builder()
    .brand("特斯拉")
    .model("Model 3")
    .engine(new ElectricEngine(283))
    .transmission(new AutomaticTransmission())
    .build();

Python 中的组合

from typing import Protocol, List, Optional
from dataclasses import dataclass

# 组件协议(接口)
class Renderer(Protocol):
    """渲染组件的协议。"""
    def render(self, content: str) -> str: ...

class Logger(Protocol):
    """日志组件的协议。"""
    def log(self, message: str, level: str) -> None: ...

class Validator(Protocol):
    """验证组件的协议。"""
    def validate(self, data: dict) -> bool: ...
    def get_errors(self) -> List[str]: ...

# 具体组件实现
class HTMLRenderer:
    """将内容渲染为 HTML。"""

    def render(self, content: str) -> str:
        return f"<html><body>{content}</body></html>"

class MarkdownRenderer:
    """将内容渲染为 Markdown。"""

    def render(self, content: str) -> str:
        return f"# {content}

渲染为 Markdown"

class FileLogger:
    """将消息记录到文件。"""

    def __init__(self, filename: str):
        self.filename = filename

    def log(self, message: str, level: str) -> None:
        with open(self.filename, 'a') as f:
            f.write(f"[{level}] {message}
")

class ConsoleLogger:
    """将消息记录到控制台。"""

    def log(self, message: str, level: str) -> None:
        print(f"[{level}] {message}")

class EmailValidator:
    """验证电子邮件地址。"""

    def __init__(self):
        self.errors: List[str] = []

    def validate(self, data: dict) -> bool:
        self.errors = []
        email = data.get('email', '')

        if not email:
            self.errors.append("电子邮件必填")
            return False

        if '@' not in email:
            self.errors.append("电子邮件必须包含 @")
            return False

        if '.' not in email.split('@')[1]:
            self.errors.append("电子邮件必须有有效域名")
            return False

        return True

    def get_errors(self) -> List[str]:
        return self.errors

# 使用依赖注入的组合类
class UserService:
    """由各种组件组成的服务。"""

    def __init__(
        self,
        renderer: Renderer,
        logger: Logger,
        validator: Validator
    ):
        self._renderer = renderer
        self._logger = logger
        self._validator = validator

    def create_user(self, user_data: dict) -> Optional[str]:
        """使用组合组件创建用户。"""
        self._logger.log(f"创建用户: {user_data.get('email')}", "INFO")

        # 使用验证器组件
        if not self._validator.validate(user_data):
            errors = self._validator.get_errors()
            self._logger.log(f"验证失败: {errors}", "ERROR")
            return None

        # 处理用户创建
        user_content = f"用户已创建: {user_data['email']}"

        # 使用渲染器组件
        rendered = self._renderer.render(user_content)
        self._logger.log("用户创建成功", "INFO")

        return rendered

# 运行时组件交换
class CompositeLogger:
    """委托给多个日志记录器的日志记录器。"""

    def __init__(self, loggers: List[Logger]):
        self._loggers = loggers

    def log(self, message: str, level: str) -> None:
        for logger in self._loggers:
            logger.log(message, level)

    def add_logger(self, logger: Logger) -> None:
        self._loggers.append(logger)

# 不同组合的使用
html_service = UserService(
    renderer=HTMLRenderer(),
    logger=ConsoleLogger(),
    validator=EmailValidator()
)

markdown_service = UserService(
    renderer=MarkdownRenderer(),
    logger=CompositeLogger([ConsoleLogger(), FileLogger('app.log')]),
    validator=EmailValidator()
)

C# 中带组合的策略模式

// 策略接口
public interface IPaymentStrategy
{
    PaymentResult ProcessPayment(decimal amount);
    bool IsAvailable();
}

public interface IShippingStrategy
{
    decimal CalculateCost(decimal weight, string destination);
    int EstimateDeliveryDays();
}

public interface IDiscountStrategy
{
    decimal ApplyDiscount(decimal originalPrice);
}

// 具体策略
public class CreditCardPayment : IPaymentStrategy
{
    private readonly string _cardNumber;
    private readonly string _cvv;

    public CreditCardPayment(string cardNumber, string cvv)
    {
        _cardNumber = cardNumber;
        _cvv = cvv;
    }

    public PaymentResult ProcessPayment(decimal amount)
    {
        // 信用卡处理逻辑
        Console.WriteLine($"处理 ${amount} 通过信用卡");
        return PaymentResult.Success(Guid.NewGuid().ToString());
    }

    public bool IsAvailable() => true;
}

public class PayPalPayment : IPaymentStrategy
{
    private readonly string _email;

    public PayPalPayment(string email)
    {
        _email = email;
    }

    public PaymentResult ProcessPayment(decimal amount)
    {
        Console.WriteLine($"处理 ${amount} 通过 PayPal");
        return PaymentResult.Success(Guid.NewGuid().ToString());
    }

    public bool IsAvailable() => true;
}

public class StandardShipping : IShippingStrategy
{
    public decimal CalculateCost(decimal weight, string destination)
    {
        return weight * 2.5m;
    }

    public int EstimateDeliveryDays() => 7;
}

public class ExpressShipping : IShippingStrategy
{
    public decimal CalculateCost(decimal weight, string destination)
    {
        return weight * 5.0m;
    }

    public int EstimateDeliveryDays() => 2;
}

public class PercentageDiscount : IDiscountStrategy
{
    private readonly decimal _percentage;

    public PercentageDiscount(decimal percentage)
    {
        _percentage = percentage;
    }

    public decimal ApplyDiscount(decimal originalPrice)
    {
        return originalPrice * (1 - _percentage / 100);
    }
}

public class FixedAmountDiscount : IDiscountStrategy
{
    private readonly decimal _amount;

    public FixedAmountDiscount(decimal amount)
    {
        _amount = amount;
    }

    public decimal ApplyDiscount(decimal originalPrice)
    {
        return Math.Max(0, originalPrice - _amount);
    }
}

// 组合的订单处理器
public class OrderProcessor
{
    private IPaymentStrategy _paymentStrategy;
    private IShippingStrategy _shippingStrategy;
    private IDiscountStrategy? _discountStrategy;

    public OrderProcessor(
        IPaymentStrategy paymentStrategy,
        IShippingStrategy shippingStrategy,
        IDiscountStrategy? discountStrategy = null)
    {
        _paymentStrategy = paymentStrategy ?? throw new ArgumentNullException(nameof(paymentStrategy));
        _shippingStrategy = shippingStrategy ?? throw new ArgumentNullException(nameof(shippingStrategy));
        _discountStrategy = discountStrategy;
    }

    // 策略可在运行时更改
    public void SetPaymentStrategy(IPaymentStrategy strategy)
    {
        _paymentStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy));
    }

    public void SetShippingStrategy(IShippingStrategy strategy)
    {
        _shippingStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy));
    }

    public void SetDiscountStrategy(IDiscountStrategy? strategy)
    {
        _discountStrategy = strategy;
    }

    public OrderResult ProcessOrder(Order order)
    {
        // 计算总计
        decimal subtotal = order.Items.Sum(item => item.Price * item.Quantity);

        // 应用折扣
        decimal total = _discountStrategy?.ApplyDiscount(subtotal) ?? subtotal;

        // 计算运费
        decimal shippingCost = _shippingStrategy.CalculateCost(order.TotalWeight, order.Destination);
        total += shippingCost;

        // 处理付款
        if (!_paymentStrategy.IsAvailable())
        {
            return OrderResult.Failed("付款方式不可用");
        }

        var paymentResult = _paymentStrategy.ProcessPayment(total);
        if (!paymentResult.IsSuccess)
        {
            return OrderResult.Failed("付款失败");
        }

        return OrderResult.Success(
            order.Id,
            total,
            _shippingStrategy.EstimateDeliveryDays()
        );
    }
}

// 使用
var processor = new OrderProcessor(
    new CreditCardPayment("1234-5678-9012-3456", "123"),
    new StandardShipping(),
    new PercentageDiscount(10)
);

// 运行时更改策略
processor.SetShippingStrategy(new ExpressShipping());
processor.SetDiscountStrategy(new FixedAmountDiscount(20));

混合模式

Python 中的混合

from typing import Any
import json

# 提供特定功能的混合类
class JsonSerializableMixin:
    """添加 JSON 序列化的混合。"""

    def to_json(self) -> str:
        """将对象序列化为 JSON。"""
        return json.dumps(self.__dict__)

    @classmethod
    def from_json(cls, json_str: str) -> Any:
        """从 JSON 反序列化。"""
        data = json.loads(json_str)
        return cls(**data)

class TimestampMixin:
    """添加时间戳跟踪的混合。"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.created_at = datetime.now()
        self.updated_at = datetime.now()

    def touch(self) -> None:
        """更新 updated_at 时间戳。"""
        self.updated_at = datetime.now()

class ValidationMixin:
    """添加验证能力的混合。"""

    def validate(self) -> bool:
        """验证对象状态。"""
        errors = self.get_validation_errors()
        return len(errors) == 0

    def get_validation_errors(self) -> List[str]:
        """获取验证错误列表。"""
        errors = []
        for attr_name, attr_value in self.__dict__.items():
            if attr_value is None and not attr_name.startswith('_'):
                errors.append(f"{attr_name} 必填")
        return errors

class AuditMixin:
    """添加审计追踪的混合。"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._changes: List[dict] = []

    def record_change(self, field: str, old_value: Any, new_value: Any) -> None:
        """记录变更到审计追踪。"""
        self._changes.append({
            'field': field,
            'old_value': old_value,
            'new_value': new_value,
            'timestamp': datetime.now()
        })

    def get_audit_trail(self) -> List[dict]:
        """获取审计追踪。"""
        return self._changes.copy()

# 结合混合的基类
class User(TimestampMixin, JsonSerializableMixin, ValidationMixin, AuditMixin):
    """具有多种混合行为的用户类。"""

    def __init__(self, username: str, email: str, age: int):
        super().__init__()
        self._username = username
        self._email = email
        self._age = age

    @property
    def username(self) -> str:
        return self._username

    @username.setter
    def username(self, value: str) -> None:
        old_value = self._username
        self._username = value
        self.touch()
        self.record_change('username', old_value, value)

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

    @email.setter
    def email(self, value: str) -> None:
        old_value = self._email
        self._email = value
        self.touch()
        self.record_change('email', old_value, value)

    def get_validation_errors(self) -> List[str]:
        """重写以添加特定验证。"""
        errors = super().get_validation_errors()

        if len(self._username) < 3:
            errors.append("用户名必须至少 3 个字符")

        if '@' not in self._email:
            errors.append("电子邮件必须有效")

        if self._age < 18:
            errors.append("用户必须至少 18 岁")

        return errors

# 使用
user = User("john_doe", "john@example.com", 25)
user.username = "jane_doe"
print(user.to_json())
print(user.get_audit_trail())
print(user.validate())

接口隔离

Java 中的多接口

// 隔离的接口 - 客户端仅依赖所需部分
interface Readable {
    String read();
}

interface Writable {
    void write(String content);
}

interface Appendable {
    void append(String content);
}

interface Searchable {
    List<String> search(String query);
}

// 只读文档
class ReadOnlyDocument implements Readable {
    private final String content;

    public ReadOnlyDocument(String content) {
        this.content = content;
    }

    @Override
    public String read() {
        return content;
    }
}

// 全功能文档
class Document implements Readable, Writable, Appendable, Searchable {
    private StringBuilder content;

    public Document(String initialContent) {
        this.content = new StringBuilder(initialContent);
    }

    @Override
    public String read() {
        return content.toString();
    }

    @Override
    public void write(String newContent) {
        content = new StringBuilder(newContent);
    }

    @Override
    public void append(String additionalContent) {
        content.append(additionalContent);
    }

    @Override
    public List<String> search(String query) {
        List<String> results = new ArrayList<>();
        String[] lines = content.toString().split("
");
        for (String line : lines) {
            if (line.contains(query)) {
                results.add(line);
            }
        }
        return results;
    }
}

// 仅需要读取的客户端
class DocumentViewer {
    private final Readable document;

    public DocumentViewer(Readable document) {
        this.document = document;
    }

    public void display() {
        System.out.println(document.read());
    }
}

// 需要读取和搜索的客户端
class DocumentSearcher {
    private final Readable readable;
    private final Searchable searchable;

    public DocumentSearcher(Readable readable, Searchable searchable) {
        this.readable = readable;
        this.searchable = searchable;
    }

    public void findAndDisplay(String query) {
        List<String> results = searchable.search(query);
        results.forEach(System.out::println);
    }
}

何时使用此技能

在以下情况下应用继承和组合:

  1. 设计具有共享行为的类层次结构
  2. 建模 IS-A 关系(继承)
  3. 建模 HAS-A 关系(组合)
  4. 创建可扩展框架
  5. 实现模板方法
  6. 构建灵活、可配置的系统
  7. 避免相关类之间的代码重复
  8. 支持运行时行为更改(组合)
  9. 实现策略模式
  10. 创建插件架构
  11. 使用依赖注入构建可测试代码
  12. 避免深层继承层次结构
  13. 支持行为的多种实现
  14. 创建可重用组件
  15. 实现接口隔离

最佳实践

  1. 优先选择组合而非继承以获得灵活性
  2. 使用继承处理真正的 IS-A 关系
  3. 保持继承层次浅(最多 2-3 层)
  4. 在适当时使基类抽象
  5. 使用接口/协议作为行为契约
  6. 偏好小型、聚焦的接口而非大型接口
  7. 使用依赖注入实现可组合设计
  8. 清晰记录模板方法模式
  9. 需要时正确重写方法并调用 super
  10. 使用 final/sealed 防止进一步继承
  11. 从小型、单一用途的组件组合行为
  12. 使用策略模式实现运行时行为更改
  13. 避免受保护字段,使用受保护方法
  14. 尽可能使组合对象不可变
  15. 独立测试每个组件

常见陷阱

  1. 创建深层继承层次结构
  2. 仅为了代码重用而使用继承
  3. 从具体类继承
  4. 破坏里氏替换原则
  5. 创建具有过多职责的上帝类
  6. 过度使用继承,而组合可能更好
  7. 使所有类继承自一个公共基类
  8. 使用受保护字段而非私有
  9. 在构造函数中忘记调用 super()
  10. 在组合中创建循环依赖
  11. 不考虑脆弱基类问题
  12. 使用实现继承而非接口继承
  13. 通过继承创建紧耦合
  14. 未在子类中正确重写 equals/hashCode
  15. 在基类中混合关注点

资源