OOP多态性Skill oop-polymorphism

OOP多态性是面向对象编程的关键技能,用于通过接口、抽象类和运行时类型替换实现多态行为,创建灵活、可扩展的系统。适用于插件架构、策略模式、依赖注入等场景,提升代码可维护性和可测试性。关键词:多态性、接口、抽象类、运行时类型、灵活系统、可扩展设计、插件架构、策略模式、依赖注入。

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

名称: oop-polymorphism 用户可调用: false 描述: 在实现面向对象设计中的多态性和接口时使用。用于创建具有可互换组件的灵活、可扩展系统。 允许的工具:

  • Bash
  • Read

OOP 多态性

掌握多态性,以创建灵活、可扩展的面向对象系统。此技能侧重于通过接口、抽象类和运行时类型替换理解和应用多态行为。

理解多态性

多态性允许通过共同接口统一处理不同类型的对象。它使代码能够与抽象而非具体实现一起工作。

Java 中的基于接口的多态性

// 所有支付方法的共同接口
public interface PaymentMethod {
    PaymentResult process(BigDecimal amount);
    boolean isValid();
    String getDisplayName();
}

// 具体实现
public class CreditCard implements PaymentMethod {
    private final String cardNumber;
    private final String cardholderName;
    private final String expiryDate;
    private final String cvv;

    public CreditCard(String cardNumber, String cardholderName, String expiryDate, String cvv) {
        this.cardNumber = cardNumber;
        this.cardholderName = cardholderName;
        this.expiryDate = expiryDate;
        this.cvv = cvv;
    }

    @Override
    public PaymentResult process(BigDecimal amount) {
        if (!isValid()) {
            return PaymentResult.failed("无效信用卡");
        }

        // 信用卡处理逻辑
        String transactionId = UUID.randomUUID().toString();
        System.out.println("通过信用卡处理 $" + amount + ",卡号末尾 " +
            cardNumber.substring(cardNumber.length() - 4));

        return PaymentResult.success(transactionId, amount);
    }

    @Override
    public boolean isValid() {
        return cardNumber != null &&
               cardNumber.length() == 16 &&
               !isExpired(expiryDate);
    }

    @Override
    public String getDisplayName() {
        return "信用卡末尾 " + cardNumber.substring(cardNumber.length() - 4);
    }

    private boolean isExpired(String expiryDate) {
        // 过期日期验证逻辑
        return false;
    }
}

public class PayPal implements PaymentMethod {
    private final String email;
    private final String password;

    public PayPal(String email, String password) {
        this.email = email;
        this.password = password;
    }

    @Override
    public PaymentResult process(BigDecimal amount) {
        if (!isValid()) {
            return PaymentResult.failed("无效PayPal凭据");
        }

        String transactionId = UUID.randomUUID().toString();
        System.out.println("通过PayPal账户处理 $" + amount + ",邮箱 " + email);

        return PaymentResult.success(transactionId, amount);
    }

    @Override
    public boolean isValid() {
        return email != null && email.contains("@") && password != null;
    }

    @Override
    public String getDisplayName() {
        return "PayPal (" + email + ")";
    }
}

public class BankTransfer implements PaymentMethod {
    private final String accountNumber;
    private final String routingNumber;
    private final String accountHolderName;

    public BankTransfer(String accountNumber, String routingNumber, String accountHolderName) {
        this.accountNumber = accountNumber;
        this.routingNumber = routingNumber;
        this.accountHolderName = accountHolderName;
    }

    @Override
    public PaymentResult process(BigDecimal amount) {
        if (!isValid()) {
            return PaymentResult.failed("无效银行账户");
        }

        String transactionId = UUID.randomUUID().toString();
        System.out.println("通过银行转账处理 $" + amount + ",账户持有人 " + accountHolderName);

        return PaymentResult.success(transactionId, amount);
    }

    @Override
    public boolean isValid() {
        return accountNumber != null &&
               routingNumber != null &&
               accountNumber.length() > 0;
    }

    @Override
    public String getDisplayName() {
        return "银行账户 (" + accountHolderName + ")";
    }
}

// 多态使用
public class PaymentProcessor {
    private final List<PaymentMethod> paymentMethods;

    public PaymentProcessor() {
        this.paymentMethods = new ArrayList<>();
    }

    public void addPaymentMethod(PaymentMethod method) {
        paymentMethods.add(method);
    }

    public PaymentResult processPayment(BigDecimal amount) {
        // 尝试每种支付方法直到成功
        for (PaymentMethod method : paymentMethods) {
            if (method.isValid()) {
                System.out.println("尝试支付使用 " + method.getDisplayName());
                PaymentResult result = method.process(amount);

                if (result.isSuccess()) {
                    return result;
                }
            }
        }

        return PaymentResult.failed("无可用有效支付方法");
    }

    public List<String> getAvailablePaymentMethods() {
        return paymentMethods.stream()
            .filter(PaymentMethod::isValid)
            .map(PaymentMethod::getDisplayName)
            .collect(Collectors.toList());
    }
}

// 使用 - 多态性在行动中
PaymentProcessor processor = new PaymentProcessor();
processor.addPaymentMethod(new CreditCard("1234567890123456", "John Doe", "12/25", "123"));
processor.addPaymentMethod(new PayPal("john@example.com", "secret"));
processor.addPaymentMethod(new BankTransfer("9876543210", "123456789", "John Doe"));

PaymentResult result = processor.processPayment(new BigDecimal("99.99"));

Python 中的基于协议的多态性

from typing import Protocol, List, Optional
from abc import ABC, abstractmethod
from dataclasses import dataclass
import json

# 协议定义接口(结构化类型)
class Serializable(Protocol):
    """可序列化对象的协议。"""

    def to_dict(self) -> dict:
        """转换为字典。"""
        ...

    def to_json(self) -> str:
        """转换为JSON字符串。"""
        ...

# 另一个协议
class Identifiable(Protocol):
    """具有ID的对象的协议。"""

    @property
    def id(self) -> str:
        """获取唯一标识符。"""
        ...

# 具体实现
@dataclass
class User:
    """用户实现,具有两个协议。"""

    _id: str
    username: str
    email: str
    age: int

    @property
    def id(self) -> str:
        return self._id

    def to_dict(self) -> dict:
        return {
            'id': self._id,
            'username': self.username,
            'email': self.email,
            'age': self.age
        }

    def to_json(self) -> str:
        return json.dumps(self.to_dict())

@dataclass
class Product:
    """产品实现,具有两个协议。"""

    _id: str
    name: str
    price: float
    category: str

    @property
    def id(self) -> str:
        return self._id

    def to_dict(self) -> dict:
        return {
            'id': self._id,
            'name': self.name,
            'price': self.price,
            'category': self.category
        }

    def to_json(self) -> str:
        return json.dumps(self.to_dict())

@dataclass
class Order:
    """订单实现。"""

    _id: str
    user_id: str
    items: List[str]
    total: float

    @property
    def id(self) -> str:
        return self._id

    def to_dict(self) -> dict:
        return {
            'id': self._id,
            'user_id': self.user_id,
            'items': self.items,
            'total': self.total
        }

    def to_json(self) -> str:
        return json.dumps(self.to_dict())

# 使用协议的多态函数
def save_to_file(obj: Serializable, filename: str) -> None:
    """保存任何可序列化对象到文件。"""
    with open(filename, 'w') as f:
        f.write(obj.to_json())

def get_id(obj: Identifiable) -> str:
    """从任何可标识对象获取ID。"""
    return obj.id
def serialize_batch(objects: List[Serializable]) -> str:
    """序列化多个对象。"""
    return json.dumps([obj.to_dict() for obj in objects])

# 适用于任何实现协议的对象
user = User("u1", "alice", "alice@example.com", 30)
product = Product("p1", "Laptop", 999.99, "Electronics")
order = Order("o1", "u1", ["p1"], 999.99)

save_to_file(user, "user.json")
save_to_file(product, "product.json")

all_objects = [user, product, order]
batch_json = serialize_batch(all_objects)

Python 中的抽象基类

from abc import ABC, abstractmethod
from typing import List, Dict, Any
from datetime import datetime

# 定义契约的抽象基类
class DataStore(ABC):
    """数据存储的抽象基类。"""

    @abstractmethod
    def connect(self) -> None:
        """建立到数据存储的连接。"""
        pass

    @abstractmethod
    def disconnect(self) -> None:
        """关闭到数据存储的连接。"""
        pass

    @abstractmethod
    def save(self, key: str, value: Any) -> bool:
        """保存值并指定键。"""
        pass

    @abstractmethod
    def load(self, key: str) -> Optional[Any]:
        """加载指定键的值。"""
        pass

    @abstractmethod
    def delete(self, key: str) -> bool:
        """删除指定键的值。"""
        pass

    @abstractmethod
    def list_keys(self) -> List[str]:
        """列出存储中的所有键。"""
        pass

    # 具有默认实现的具体方法
    def exists(self, key: str) -> bool:
        """检查键是否存在。"""
        return self.load(key) is not None

    def save_batch(self, items: Dict[str, Any]) -> int:
        """保存多个项目。"""
        count = 0
        for key, value in items.items():
            if self.save(key, value):
                count += 1
        return count

# 具体实现 - 内存存储
class MemoryStore(DataStore):
    """内存数据存储实现。"""

    def __init__(self):
        self._data: Dict[str, Any] = {}
        self._connected = False

    def connect(self) -> None:
        self._connected = True
        print("内存存储已连接")

    def disconnect(self) -> None:
        self._connected = False
        print("内存存储已断开连接")

    def save(self, key: str, value: Any) -> bool:
        if not self._connected:
            raise RuntimeError("未连接")
        self._data[key] = value
        return True

    def load(self, key: str) -> Optional[Any]:
        if not self._connected:
            raise RuntimeError("未连接")
        return self._data.get(key)

    def delete(self, key: str) -> bool:
        if not self._connected:
            raise RuntimeError("未连接")
        if key in self._data:
            del self._data[key]
            return True
        return False

    def list_keys(self) -> List[str]:
        if not self._connected:
            raise RuntimeError("未连接")
        return list(self._data.keys())

# 具体实现 - 基于文件的存储
class FileStore(DataStore):
    """基于文件的数据存储实现。"""

    def __init__(self, directory: str):
        self._directory = directory
        self._connected = False

    def connect(self) -> None:
        import os
        os.makedirs(self._directory, exist_ok=True)
        self._connected = True
        print(f"文件存储已连接: {self._directory}")

    def disconnect(self) -> None:
        self._connected = False
        print("文件存储已断开连接")

    def save(self, key: str, value: Any) -> bool:
        if not self._connected:
            raise RuntimeError("未连接")

        import json
        filepath = os.path.join(self._directory, f"{key}.json")
        try:
            with open(filepath, 'w') as f:
                json.dump(value, f)
            return True
        except Exception as e:
            print(f"保存 {key} 错误: {e}")
            return False

    def load(self, key: str) -> Optional[Any]:
        if not self._connected:
            raise RuntimeError("未连接")

        import json
        filepath = os.path.join(self._directory, f"{key}.json")
        try:
            with open(filepath, 'r') as f:
                return json.load(f)
        except FileNotFoundError:
            return None
        except Exception as e:
            print(f"加载 {key} 错误: {e}")
            return None

    def delete(self, key: str) -> bool:
        if not self._connected:
            raise RuntimeError("未连接")

        import os
        filepath = os.path.join(self._directory, f"{key}.json")
        try:
            os.remove(filepath)
            return True
        except FileNotFoundError:
            return False

    def list_keys(self) -> List[str]:
        if not self._connected:
            raise RuntimeError("未连接")

        import os
        return [
            f[:-5] for f in os.listdir(self._directory)
            if f.endswith('.json')
        ]

# 多态使用
class DataManager:
    """管理器,适用于任何DataStore。"""

    def __init__(self, store: DataStore):
        self._store = store

    def __enter__(self):
        self._store.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._store.disconnect()

    def backup(self, source_store: DataStore) -> int:
        """从另一个存储备份。"""
        count = 0
        for key in source_store.list_keys():
            value = source_store.load(key)
            if value is not None and self._store.save(key, value):
                count += 1
        return count

    def migrate(self, target_store: DataStore) -> int:
        """将数据迁移到另一个存储。"""
        count = 0
        for key in self._store.list_keys():
            value = self._store.load(key)
            if value is not None and target_store.save(key, value):
                count += 1
        return count

# 使用不同实现
with DataManager(MemoryStore()) as manager:
    manager._store.save("user:1", {"name": "Alice", "age": 30})

with DataManager(FileStore("./data")) as manager:
    manager._store.save("user:2", {"name": "Bob", "age": 25})

TypeScript 多态性

// 基于接口的多态性
interface Logger {
  log(message: string, level: string): void;
  flush(): void;
}

interface Formatter {
  format(message: string, level: string): string;
}

// 具体实现
class ConsoleLogger implements Logger {
  private formatter: Formatter;

  constructor(formatter: Formatter) {
    this.formatter = formatter;
  }

  log(message: string, level: string): void {
    const formatted = this.formatter.format(message, level);
    console.log(formatted);
  }

  flush(): void {
    // 控制台日志立即输出,无需刷新
  }
}

class FileLogger implements Logger {
  private formatter: Formatter;
  private buffer: string[] = [];
  private readonly filename: string;

  constructor(filename: string, formatter: Formatter) {
    this.filename = filename;
    this.formatter = formatter;
  }

  log(message: string, level: string): void {
    const formatted = this.formatter.format(message, level);
    this.buffer.push(formatted);

    if (this.buffer.length >= 10) {
      this.flush();
    }
  }

  flush(): void {
    if (this.buffer.length === 0) return;

    // 写入文件(简化)
    const content = this.buffer.join('
');
    console.log(`写入到 ${this.filename}:`, content);
    this.buffer = [];
  }
}

class JsonFormatter implements Formatter {
  format(message: string, level: string): string {
    return JSON.stringify({
      message,
      level,
      timestamp: new Date().toISOString()
    });
  }
}

class TextFormatter implements Formatter {
  format(message: string, level: string): string {
    const timestamp = new Date().toISOString();
    return `[${timestamp}] [${level}] ${message}`;
  }
}

// 使用多态性的组合日志记录器
class MultiLogger implements Logger {
  private loggers: Logger[] = [];

  addLogger(logger: Logger): void {
    this.loggers.push(logger);
  }

  log(message: string, level: string): void {
    for (const logger of this.loggers) {
      logger.log(message, level);
    }
  }

  flush(): void {
    for (const logger of this.loggers) {
      logger.flush();
    }
  }
}

// 使用多态性的应用程序
class Application {
  private logger: Logger;

  constructor(logger: Logger) {
    this.logger = logger;
  }

  run(): void {
    this.logger.log("应用程序启动", "INFO");
    this.processData();
    this.logger.log("应用程序完成", "INFO");
    this.logger.flush();
  }

  private processData(): void {
    this.logger.log("处理数据", "DEBUG");
    // 处理逻辑
  }
}

// 使用 - 可交换实现
const jsonFormatter = new JsonFormatter();
const textFormatter = new TextFormatter();

const consoleLogger = new ConsoleLogger(textFormatter);
const fileLogger = new FileLogger("app.log", jsonFormatter);

const multiLogger = new MultiLogger();
multiLogger.addLogger(consoleLogger);
multiLogger.addLogger(fileLogger);

// 应用程序适用于任何Logger实现
const app = new Application(multiLogger);
app.run();

C# 多态性与接口

// 通知服务的接口
public interface INotificationService
{
    Task SendAsync(string recipient, string subject, string body);
    bool IsAvailable();
    string GetServiceName();
}

// 具体实现
public class EmailNotificationService : INotificationService
{
    private readonly string _smtpServer;
    private readonly int _port;
    private readonly string _username;
    private readonly string _password;

    public EmailNotificationService(string smtpServer, int port, string username, string password)
    {
        _smtpServer = smtpServer;
        _port = port;
        _username = username;
        _password = password;
    }

    public async Task SendAsync(string recipient, string subject, string body)
    {
        if (!IsAvailable())
            throw new InvalidOperationException("电子邮件服务不可用");

        Console.WriteLine($"发送电子邮件给 {recipient}");
        Console.WriteLine($"主题: {subject}");
        Console.WriteLine($"正文: {body}");

        // 模拟发送电子邮件
        await Task.Delay(100);
    }

    public bool IsAvailable()
    {
        return !string.IsNullOrEmpty(_smtpServer);
    }

    public string GetServiceName()
    {
        return "电子邮件";
    }
}

public class SmsNotificationService : INotificationService
{
    private readonly string _apiKey;
    private readonly string _phoneNumber;

    public SmsNotificationService(string apiKey, string phoneNumber)
    {
        _apiKey = apiKey;
        _phoneNumber = phoneNumber;
    }

    public async Task SendAsync(string recipient, string subject, string body)
    {
        if (!IsAvailable())
            throw new InvalidOperationException("短信服务不可用");

        Console.WriteLine($"发送短信给 {recipient}");
        Console.WriteLine($"消息: {subject} - {body}");

        await Task.Delay(50);
    }

    public bool IsAvailable()
    {
        return !string.IsNullOrEmpty(_apiKey);
    }

    public string GetServiceName()
    {
        return "短信";
    }
}

public class PushNotificationService : INotificationService
{
    private readonly string _appId;
    private readonly string _apiKey;

    public PushNotificationService(string appId, string apiKey)
    {
        _appId = appId;
        _apiKey = apiKey;
    }

    public async Task SendAsync(string recipient, string subject, string body)
    {
        if (!IsAvailable())
            throw new InvalidOperationException("推送通知服务不可用");

        Console.WriteLine($"发送推送通知给 {recipient}");
        Console.WriteLine($"标题: {subject}");
        Console.WriteLine($"正文: {body}");

        await Task.Delay(30);
    }

    public bool IsAvailable()
    {
        return !string.IsNullOrEmpty(_appId) && !string.IsNullOrEmpty(_apiKey);
    }

    public string GetServiceName()
    {
        return "推送通知";
    }
}

// 多态通知管理器
public class NotificationManager
{
    private readonly List<INotificationService> _services;

    public NotificationManager()
    {
        _services = new List<INotificationService>();
    }

    public void RegisterService(INotificationService service)
    {
        _services.Add(service);
    }

    public async Task NotifyAsync(string recipient, string subject, string body)
    {
        var availableServices = _services.Where(s => s.IsAvailable()).ToList();

        if (!availableServices.Any())
        {
            throw new InvalidOperationException("无可用通知服务");
        }

        Console.WriteLine($"通过 {availableServices.Count} 个服务发送");

        var tasks = availableServices.Select(service =>
            NotifyWithServiceAsync(service, recipient, subject, body)
        );

        await Task.WhenAll(tasks);
    }

    private async Task NotifyWithServiceAsync(
        INotificationService service,
        string recipient,
        string subject,
        string body)
    {
        try
        {
            await service.SendAsync(recipient, subject, body);
            Console.WriteLine($"{service.GetServiceName()} 通知发送成功");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"{service.GetServiceName()} 通知失败: {ex.Message}");
        }
    }

    public List<string> GetAvailableServices()
    {
        return _services
            .Where(s => s.IsAvailable())
            .Select(s => s.GetServiceName())
            .ToList();
    }
}

// 使用
var manager = new NotificationManager();
manager.RegisterService(new EmailNotificationService("smtp.example.com", 587, "user", "pass"));
manager.RegisterService(new SmsNotificationService("api-key", "+1234567890"));
manager.RegisterService(new PushNotificationService("app-id", "api-key"));

await manager.NotifyAsync("user@example.com", "欢迎", "欢迎使用我们的服务!");

方法重载

Java 中的重载

public class Calculator {
    // 方法重载 - 相同名称,不同参数

    // 添加两个整数
    public int add(int a, int b) {
        return a + b;
    }

    // 添加三个整数
    public int add(int a, int b, int c) {
        return a + b + c;
    }

    // 添加两个双精度数
    public double add(double a, double b) {
        return a + b;
    }

    // 添加整数数组
    public int add(int[] numbers) {
        int sum = 0;
        for (int num : numbers) {
            sum += num;
        }
        return sum;
    }

    // 添加不同类型组合
    public double add(int a, double b) {
        return a + b;
    }

    public double add(double a, int b) {
        return a + b;
    }
}

// 字符串格式化与重载
public class Formatter {
    public String format(String text) {
        return text.trim();
    }

    public String format(String text, boolean uppercase) {
        String trimmed = format(text);
        return uppercase ? trimmed.toUpperCase() : trimmed.toLowerCase();
    }

    public String format(String text, int maxLength) {
        String trimmed = format(text);
        return trimmed.length() > maxLength
            ? trimmed.substring(0, maxLength) + "..."
            : trimmed;
    }

    public String format(String text, boolean uppercase, int maxLength) {
        String formatted = format(text, uppercase);
        return format(formatted, maxLength);
    }
}

C# 中的重载

public class DocumentProcessor
{
    // 处理字符串内容
    public ProcessResult Process(string content)
    {
        return new ProcessResult
        {
            Type = "text",
            Length = content.Length,
            ProcessedContent = content.Trim()
        };
    }

    // 处理字节数组(二进制内容)
    public ProcessResult Process(byte[] content)
    {
        return new ProcessResult
        {
            Type = "binary",
            Length = content.Length,
            ProcessedContent = Convert.ToBase64String(content)
        };
    }

    // 带选项处理
    public ProcessResult Process(string content, ProcessOptions options)
    {
        var result = Process(content);

        if (options.RemoveWhitespace)
        {
            result.ProcessedContent = Regex.Replace(
                result.ProcessedContent.ToString(),
                @"\s+",
                " "
            );
        }

        if (options.MaxLength > 0)
        {
            var text = result.ProcessedContent.ToString();
            result.ProcessedContent = text.Length > options.MaxLength
                ? text.Substring(0, options.MaxLength)
                : text;
        }

        return result;
    }

    // 处理文件
    public async Task<ProcessResult> ProcessAsync(FileInfo file)
    {
        var content = await File.ReadAllTextAsync(file.FullName);
        return Process(content);
    }

    // 处理流
    public async Task<ProcessResult> ProcessAsync(Stream stream)
    {
        using var reader = new StreamReader(stream);
        var content = await reader.ReadToEndAsync();
        return Process(content);
    }
}

运算符重载

C# 运算符重载

public struct Vector3D
{
    public double X { get; }
    public double Y { get; }
    public double Z { get; }

    public Vector3D(double x, double y, double z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    // 二元运算符重载
    public static Vector3D operator +(Vector3D a, Vector3D b)
    {
        return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
    }

    public static Vector3D operator -(Vector3D a, Vector3D b)
    {
        return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
    }

    public static Vector3D operator *(Vector3D v, double scalar)
    {
        return new Vector3D(v.X * scalar, v.Y * scalar, v.Z * scalar);
    }

    public static Vector3D operator *(double scalar, Vector3D v)
    {
        return v * scalar;
    }

    public static Vector3D operator /(Vector3D v, double scalar)
    {
        if (scalar == 0)
            throw new DivideByZeroException();
        return new Vector3D(v.X / scalar, v.Y / scalar, v.Z / scalar);
    }

    // 一元运算符重载
    public static Vector3D operator -(Vector3D v)
    {
        return new Vector3D(-v.X, -v.Y, -v.Z);
    }

    // 比较运算符
    public static bool operator ==(Vector3D a, Vector3D b)
    {
        return a.X == b.X && a.Y == b.Y && a.Z == b.Z;
    }

    public static bool operator !=(Vector3D a, Vector3D b)
    {
        return !(a == b);
    }

    // 重写Object方法
    public override bool Equals(object obj)
    {
        return obj is Vector3D vector && this == vector;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(X, Y, Z);
    }

    public override string ToString()
    {
        return $"({X}, {Y}, {Z})";
    }

    // 额外向量操作
    public double Magnitude()
    {
        return Math.Sqrt(X * X + Y * Y + Z * Z);
    }

    public Vector3D Normalize()
    {
        double mag = Magnitude();
        return mag > 0 ? this / mag : this;
    }

    public double Dot(Vector3D other)
    {
        return X * other.X + Y * other.Y + Z * other.Z;
    }

    public Vector3D Cross(Vector3D other)
    {
        return new Vector3D(
            Y * other.Z - Z * other.Y,
            Z * other.X - X * other.Z,
            X * other.Y - Y * other.X
        );
    }
}

// 使用
var v1 = new Vector3D(1, 2, 3);
var v2 = new Vector3D(4, 5, 6);
var v3 = v1 + v2;  // (5, 7, 9)
var v4 = v1 * 2;   // (2, 4, 6)
var v5 = -v1;      // (-1, -2, -3)

Python 魔术方法(运算符重载)

class Money:
    """带运算符重载的货币类。"""

    def __init__(self, amount: float, currency: str = "USD"):
        self.amount = amount
        self.currency = currency

    def __add__(self, other):
        """添加两个货币金额。"""
        if isinstance(other, Money):
            if self.currency != other.currency:
                raise ValueError("无法添加不同货币")
            return Money(self.amount + other.amount, self.currency)
        elif isinstance(other, (int, float)):
            return Money(self.amount + other, self.currency)
        return NotImplemented

    def __sub__(self, other):
        """减去两个货币金额。"""
        if isinstance(other, Money):
            if self.currency != other.currency:
                raise ValueError("无法减去不同货币")
            return Money(self.amount - other.amount, self.currency)
        elif isinstance(other, (int, float)):
            return Money(self.amount - other, self.currency)
        return NotImplemented

    def __mul__(self, other):
        """货币乘以数字。"""
        if isinstance(other, (int, float)):
            return Money(self.amount * other, self.currency)
        return NotImplemented

    def __truediv__(self, other):
        """货币除以数字。"""
        if isinstance(other, (int, float)):
            if other == 0:
                raise ValueError("不能除以零")
            return Money(self.amount / other, self.currency)
        return NotImplemented

    def __eq__(self, other):
        """检查相等性。"""
        if not isinstance(other, Money):
            return False
        return self.amount == other.amount and self.currency == other.currency

    def __lt__(self, other):
        """小于比较。"""
        if not isinstance(other, Money):
            return NotImplemented
        if self.currency != other.currency:
            raise ValueError("无法比较不同货币")
        return self.amount < other.amount

    def __le__(self, other):
        """小于或等于比较。"""
        return self == other or self < other

    def __gt__(self, other):
        """大于比较。"""
        if not isinstance(other, Money):
            return NotImplemented
        if self.currency != other.currency:
            raise ValueError("无法比较不同货币")
        return self.amount > other.amount

    def __ge__(self, other):
        """大于或等于比较。"""
        return self == other or self > other

    def __str__(self):
        """字符串表示。"""
        return f"{self.currency} {self.amount:.2f}"

    def __repr__(self):
        """开发者表示。"""
        return f"Money({self.amount}, {self.currency!r})"

    def __hash__(self):
        """用于集合/字典的哈希。"""
        return hash((self.amount, self.currency))

# 使用
price = Money(19.99)
tax = Money(2.00)
total = price + tax  # Money(21.99, 'USD')
discounted = total * 0.9  # Money(19.791, 'USD')
print(total > price)  # True

鸭子类型和结构多态性

Python 中的鸭子类型

# 无显式接口 - 对象只需正确方法
class FileWriter:
    """写入文件。"""

    def __init__(self, filename: str):
        self.file = open(filename, 'w')

    def write(self, data: str) -> None:
        self.file.write(data)

    def close(self) -> None:
        self.file.close()

class StringWriter:
    """写入字符串缓冲区。"""

    def __init__(self):
        self.buffer = []

    def write(self, data: str) -> None:
        self.buffer.append(data)

    def close(self) -> None:
        pass  # 无需关闭

    def get_value(self) -> str:
        return ''.join(self.buffer)

class NetworkWriter:
    """写入网络套接字。"""

    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.connected = True

    def write(self, data: str) -> None:
        print(f"发送到 {self.host}:{self.port}: {data}")

    def close(self) -> None:
        self.connected = False
        print("连接关闭")

# 适用于任何“写入器类”对象的函数
def save_report(writer, title: str, data: List[str]) -> None:
    """使用任何写入器保存报告(鸭子类型)。"""
    writer.write(f"报告: {title}
")
    writer.write("=" * 50 + "
")

    for item in data:
        writer.write(f"- {item}
")

    writer.close()

# 所有对象都适用于相同函数
save_report(FileWriter("report.txt"), "销售", ["项目 1", "项目 2"])
save_report(StringWriter(), "库存", ["产品 A", "产品 B"])
save_report(NetworkWriter("server.com", 8080), "指标", ["CPU: 50%"])

何时使用此技能

应用多态性时:

  1. 构建可扩展插件架构
  2. 创建可互换实现
  3. 编写针对接口/抽象的代码
  4. 实现策略模式
  5. 构建依赖注入系统
  6. 创建框架钩子和扩展点
  7. 支持多种数据格式或协议
  8. 实现命令模式
  9. 构建通知或消息系统
  10. 创建抽象数据访问层
  11. 支持多种渲染引擎
  12. 实现访问者模式
  13. 构建具有多态状态的状态机
  14. 创建返回多态类型的工厂方法
  15. 设计可测试代码和模拟对象

最佳实践

  1. 面向接口编程,而非实现
  2. 使用抽象基类共享行为
  3. 保持接口小而专注(ISP)
  4. 使用多态性消除switch语句
  5. 偏好组合而非继承以提高灵活性
  6. 适当使多态方法为virtual/abstract
  7. 使用依赖注入处理多态依赖
  8. 文档化实现所需的契约/行为
  9. 在合理处提供默认实现
  10. 结合多态性使用泛型以确保类型安全
  11. 重载运算符时重写相等方法
  12. 保持多态层次浅
  13. 使用工厂模式创建多态对象
  14. 测试多态接口的每个实现
  15. 考虑使用协议/结构化类型以提高灵活性

常见陷阱

  1. 违反里氏替换原则
  2. 创建过多小接口
  3. 未跨实现提供一致行为
  4. 过度使用继承实现多态性
  5. 忘记重写Object方法(equals, hashCode)
  6. 创建泄漏抽象
  7. 在接口中混合抽象层次
  8. 未在多态代码中处理null/None
  9. 在多态类型之间创建循环依赖
  10. 重载具有相似但不同语义的方法
  11. 未考虑虚方法调用性能
  12. 使用反射而非多态性
  13. 创建具有过多方法的神接口
  14. 未测试实现的可替代性
  15. 耦合到具体类型而非抽象

资源