4. 面向对象编程:类与对象、继承与多态、特殊方法、设计模式初探

好,咱们进入第四讲。面向对象编程,简称 OOP。说实话,这个概念在风电系统里太重要了。你想想看,一个风电场有成百上千台风机,每台风机都有风速、功率、温度这些属性,还有启动、停机、偏航这些动作。这不就是天然的「对象」吗?

我个人习惯,讲 OOP 从来不讲那些「动物叫」的例子。咱们直接拿风机说事,这样你学完就能用。

4.1 类与对象:从蓝图到实体

先搞清楚两个概念:是蓝图,对象是实体。

就好比说,我们有一张风机设计图纸,这叫「类」。按照这张图纸造出来的每一台风机,就叫「对象」。每台风机都有自己的序列号、安装位置、当前发电量,但这些风机都能做同样的事情——发电、偏航、变桨。

来看代码:

class WindTurbine:
    """风机类"""
    def __init__(self, turbine_id, location, rated_power):
        self.turbine_id = turbine_id      # 风机编号
        self.location = location          # 安装位置
        self.rated_power = rated_power    # 额定功率
        self.current_power = 0.0          # 当前功率
        self.status = 'stopped'           # 运行状态
    
    def start(self):
        self.status = 'running'
        print(f'{self.turbine_id} 已启动')
    
    def stop(self):
        self.status = 'stopped'
        self.current_power = 0.0
        print(f'{self.turbine_id} 已停机')

# 创建两个风机对象
wt1 = WindTurbine('WT-001', 'A区3号', 2000)
wt2 = WindTurbine('WT-002', 'B区7号', 2000)

wt1.start()  # 输出: WT-001 已启动

我在项目中遇到过一个问题:有人把风机编号写成了数字类型,结果后面做字符串拼接时老是报错。嗯,这里要注意,__init__ 方法里的属性类型最好一开始就定好,省得后面踩坑。

小技巧:类名用大驼峰命名法(WindTurbine),属性名和方法名用小写加下划线(current_power)。这是 Python 社区的约定,别搞混了。

4.2 继承与多态:复用与扩展

继承,说白了就是「儿子继承老子的家产」。在风电系统里,我们有各种类型的风机:陆上风机、海上风机、直驱风机、双馈风机。它们有很多共同点,但又有各自的特点。

这时候继承就派上用场了:

class OffshoreTurbine(WindTurbine):
    """海上风机,继承自 WindTurbine"""
    def __init__(self, turbine_id, location, rated_power, water_depth):
        super().__init__(turbine_id, location, rated_power)
        self.water_depth = water_depth      # 水深
        self.corrosion_level = 'high'       # 腐蚀等级
    
    def start(self):
        # 多态:重写父类的 start 方法
        self._check_sea_condition()
        super().start()
    
    def _check_sea_condition(self):
        print(f'检查海况,当前水深 {self.water_depth} 米')

# 多态演示
turbines = [
    WindTurbine('WT-001', 'A区', 2000),
    OffshoreTurbine('WT-101', '海上C区', 5000, 25)
]

for t in turbines:
    t.start()  # 同一个方法名,不同行为

多态是什么意思?就是「同一个接口,不同实现」。你看上面的 start() 方法,陆上风机直接启动,海上风机要先检查海况再启动。调用者不用关心具体实现,这就是多态的魅力。

我曾经在做一个风场聚合系统时,就是因为用了多态,新增一种风机类型只需要写一个子类,主程序一行代码都不用改。那感觉,真爽。

避坑指南:我曾经见过有人把继承层次搞到五六层,结果改一个父类方法,所有子类都崩了。记住:继承不要超过三层,能用组合就别用继承。

4.3 特殊方法:让对象更「Pythonic」

Python 里有很多以双下划线开头和结尾的方法,叫特殊方法,也叫魔术方法。它们让我们的对象能像原生类型一样好用。

举个例子,你想让两台风机做比较,或者打印风机信息时更直观:

class WindTurbine:
    def __init__(self, turbine_id, power):
        self.turbine_id = turbine_id
        self.power = power
    
    def __str__(self):
        """打印时显示友好信息"""
        return f'风机 {self.turbine_id} (当前功率: {self.power}kW)'
    
    def __repr__(self):
        """调试时显示详细信息"""
        return f'WindTurbine({self.turbine_id!r}, {self.power})'
    
    def __lt__(self, other):
        """支持小于比较,用于排序"""
        return self.power < other.power
    
    def __add__(self, other):
        """支持加法,合并功率"""
        return self.power + other.power

wt1 = WindTurbine('WT-001', 1500)
wt2 = WindTurbine('WT-002', 1800)

print(wt1)           # 输出: 风机 WT-001 (当前功率: 1500kW)
print(wt1 < wt2)     # 输出: True
print(wt1 + wt2)     # 输出: 3300

你看,定义了 __str__ 后,直接 print(wt1) 就能看到有意义的信息,而不是 <__main__.WindTurbine object at 0x...>。定义了 __lt__ 后,就能直接用 sorted() 对风机列表按功率排序了。

我个人习惯,每个类至少实现 __str____repr__,调试时能省一半时间。

4.4 设计模式初探:站在巨人的肩膀上

设计模式,说白了就是「前人总结的套路」。你想想看,风电系统里有很多重复出现的问题:怎么创建不同类型的风机?怎么监控风机状态变化?怎么通知多个子系统?这些问题都有现成的解决方案。

咱们先看两个最常用的:

4.4.1 工厂模式:批量生产风机

class TurbineFactory:
    """风机工厂"""
    @staticmethod
    def create_turbine(turbine_type, **kwargs):
        if turbine_type == 'onshore':
            return WindTurbine(**kwargs)
        elif turbine_type == 'offshore':
            return OffshoreTurbine(**kwargs)
        elif turbine_type == 'direct_drive':
            return DirectDriveTurbine(**kwargs)
        else:
            raise ValueError(f'未知风机类型: {turbine_type}')

# 使用工厂
wt = TurbineFactory.create_turbine(
    'offshore',
    turbine_id='WT-101',
    location='海上C区',
    rated_power=5000,
    water_depth=25
)

工厂模式的好处是:创建对象的逻辑集中在一处,新增风机类型时只改工厂类,调用方不用动。我在做风场配置系统时就用这个模式,支持了十几种风机型号的配置。

4.4.2 观察者模式:风场监控系统

class AlarmSystem:
    """报警系统,观察者"""
    def update(self, turbine_id, status):
        if status == 'fault':
            print(f'【报警】风机 {turbine_id} 发生故障!')

class DataLogger:
    """数据记录器,观察者"""
    def update(self, turbine_id, status):
        print(f'记录: {turbine_id} 状态变为 {status}')

class WindTurbine:
    def __init__(self, turbine_id):
        self.turbine_id = turbine_id
        self._observers = []
    
    def add_observer(self, observer):
        self._observers.append(observer)
    
    def set_status(self, new_status):
        self.status = new_status
        self._notify_observers()
    
    def _notify_observers(self):
        for obs in self._observers:
            obs.update(self.turbine_id, self.status)

# 使用
wt = WindTurbine('WT-001')
wt.add_observer(AlarmSystem())
wt.add_observer(DataLogger())
wt.set_status('fault')  # 自动通知所有观察者

观察者模式在风电监控系统里太常见了。一台风机状态变化,要通知报警系统、数据记录系统、SCADA 系统、运维调度系统……用观察者模式,耦合度低,扩展性好。

核心要点:设计模式不是银弹。我见过有人为了用模式而用模式,把简单问题搞复杂了。记住:先有需求,再有模式。不要为了用模式而写代码。

知识体系总览

下面这张图,把本章的核心逻辑串起来了:

面向对象编程知识体系 OOP 四大核心 类与对象 蓝图 vs 实体 继承与多态 复用与扩展 特殊方法 __str__, __lt__ 等 设计模式 工厂、观察者等 风电应用:风机建模、监控系统、配置管理

这张图展示了 OOP 四大核心在风电系统中的位置。从上往下看:先理解类与对象这个基础,然后用继承和多态做扩展,用特殊方法让代码更优雅,最后用设计模式解决复杂问题。

好了,这一章就到这里。记住:面向对象不是语法,是一种思维方式。你写代码时多想想「这个风机有什么属性?能做什么动作?和其他风机有什么关系?」——想清楚了,代码自然就写好了。


专注资料整理