善忘技术夹 Logo
善忘技术夹
技术文章 · 710 阅读

每个开发者都应该知道的8个OOP核心概念

面向对象编程就像搭积木,掌握了这些积木块,你就能搭建出数字摩天大楼。

面向对象编程(Object-Oriented Programming,简称 OOP)诞生于20世纪60年代,但在20世纪90年代随着 Java 和 C++ 的兴起真正进入主流。

为什么几十年过去了,OOP 依然是现代编程的基石?因为它让代码更易理解、更易维护、更易扩展

今天,我们来系统掌握 OOP 的 8 个核心概念。


一、什么是 OOP?

核心思想:用”对象”来模拟现实世界

想象一下,你在描述一辆汽车:

  • 传统方式(面向过程):定义启动汽车()加速()刹车()等函数

  • OOP方式:创建一个Car对象,它知道如何启动、加速、刹车

❌ 面向过程

car_color = “红色” car_speed = 0 ​ def start_car(): global car_speed car_speed = 10 ​ def accelerate(): global car_speed car_speed += 20 ​

问题:数据和操作分离,容易出错

✅ 面向对象

class Car: def init(self, color): self.color = color self.speed = 0 ​ def start(self): self.speed = 10 print(f”{self.color}汽车启动了”) ​ def accelerate(self): self.speed += 20 print(f”加速到 {self.speed} km/h”) ​ my_car = Car(“红色”) my_car.start() my_car.accelerate() ​

优势:数据和操作封装在一起

OOP 的价值

  • 🎯 组织性:像工具箱一样,每个工具都有固定位置

  • 🔧 可维护性:修改一个类不影响其他代码

  • 🔄 可重用性:一次编写,多次使用

  • 📈 可扩展性:通过继承添加新功能


二、8种核心概念全景图


三、OOP 的四大支柱

1. 封装 (Encapsulation)

核心思想:隐藏内部细节,暴露必要的接口

现实类比:电视机

  • ✅ 你知道:电源按钮、音量按钮、HDMI接口

  • ❌ 你不知道:内部电路如何工作

  • 好处:你不需要理解内部就能使用

代码示例

// ❌ 没有封装 class BankAccount { public double balance; // 任何人都能直接修改! ​ public static void main(String[] args) { BankAccount account = new BankAccount(); account.balance = 1000000; // 😱 随便改余额! } } ​ // ✅ 使用封装 class BankAccount { private double balance; // 私有变量,外部无法访问 ​ public void deposit(double amount) { if (amount <= 0) { throw new IllegalArgumentException(“金额必须大于0”); } balance += amount; } ​ public void withdraw(double amount) { if (amount > balance) { throw new IllegalArgumentException(“余额不足”); } balance -= amount; } ​ public double getBalance() { return balance; // 只读,不能直接修改 } }

封装的三层访问控制

修饰符同一类同一包子类所有类
private
default
protected
public

最佳实践

  • ✅ 变量设为 private

  • ✅ 提供公用的 getter/setter

  • ✅ 在方法中添加业务规则验证


2. 继承 (Inheritance)

核心思想:基于现有类创建新类,复用代码

现实类比

动物 (基类) ├─ 狗 (子类) ├─ 猫 (子类) └─ 鸟 (子类) ​ 子类继承父类的特征和行为

代码示例

基类(父类)

class Animal: def init(self, name, age): self.name = name self.age = age ​ def eat(self): print(f”{self.name}在吃东西”) ​ def sleep(self): print(f”{self.name}在睡觉”) ​

子类继承父类

class Dog(Animal): def bark(self): print(f”{self.name}在汪汪叫”) ​ class Cat(Animal): def meow(self): print(f”{self.name}在喵喵叫”) ​

使用

dog = Dog(“旺财”, 3) dog.eat() # 继承自父类的方法 dog.bark() # 子类特有的方法 ​ cat = Cat(“咪咪”, 2) cat.eat() # 继承自父类的方法 cat.meow() # 子类特有的方法

方法重写 (Override)

class Animal: def make_sound(self): print(“动物发出声音”) ​ class Dog(Animal): def make_sound(self): print(“汪汪汪”) # 重写父类方法 ​ class Cat(Animal): def make_sound(self): print(“喵喵喵”) # 重写父类方法 ​

多态

animals = [Dog(“旺财”), Cat(“咪咪”)] for animal in animals: animal.make_sound() # 根据实际类型调用不同方法

继承的陷阱

  • ⚠️ 过度继承:继承层次过深(超过3层)难以理解

  • ⚠️ 脆弱基类:修改父类可能破坏所有子类

  • ⚠️ 组合优于继承:优先使用组合(has-a)而非继承(is-a)


3. 多态 (Polymorphism)

核心思想:同一接口,不同实现

现实类比

“开车”这个动作:

  • 开自动挡汽车:踩油门就走
  • 开手动挡汽车:还要控制离合器
  • 开电动车:没有发动机声音 ​ 同样是”开车”,但不同车型有不同的实现

代码示例

// 定义接口 interface Payment { void pay(double amount); } ​ // 不同的实现 class CreditCardPayment implements Payment { public void pay(double amount) { System.out.println(“使用信用卡支付 $” + amount); } } ​ class PayPalPayment implements Payment { public void pay(double amount) { System.out.println(“使用PayPal支付 $” + amount); } } ​ class WeChatPayment implements Payment { public void pay(double amount) { System.out.println(“使用微信支付 ¥” + amount); } } ​ // 多态的使用 public class PaymentProcessor { public void processPayment(Payment payment, double amount) { payment.pay(amount); // 根据实际类型调用不同实现 } ​ public static void main(String[] args) { PaymentProcessor processor = new PaymentProcessor(); ​ // 运行时决定使用哪种支付方式 Payment payment = getPaymentMethod(); processor.processPayment(payment, 100.0); } }

多态的两种形式

类型实现方式示例
编译时多态方法重载print(int) vs print(String)
运行时多态方法重写Animal.makeSound()

多态的好处

  • 灵活性:可以随时添加新实现

  • 可扩展性:不需要修改现有代码

  • 解耦:调用者不需要知道具体实现


4. 抽象 (Abstraction)

核心思想:隐藏复杂细节,展示必要功能

现实类比

驾驶员不需要知道:

  • 发动机如何工作
  • 变速箱如何换挡
  • 刹车系统如何运作

驾驶员只需要知道:

  • 方向盘控制方向
  • 油门加速
  • 刹车减速

代码示例

from abc import ABC, abstractmethod

抽象类(不能直接实例化)

class Shape(ABC): @abstractmethod def area(self): pass # 子类必须实现

@abstractmethod
def perimeter(self):
    pass  # 子类必须实现

具体类

class Circle(Shape): def init(self, radius): self.radius = radius

def area(self):
    return 3.14 * self.radius ** 2

def perimeter(self):
    return 2 * 3.14 * self.radius

class Rectangle(Shape): def init(self, width, height): self.width = width self.height = height

def area(self):
    return self.width * self.height

def perimeter(self):
    return 2 * (self.width + self.height)

使用

shapes = [Circle(5), Rectangle(4, 6)] for shape in shapes: print(f”面积: {shape.area()}”) print(f”周长: {shape.perimeter()}”)

抽象 vs 接口

维度抽象类接口
实现可以有部分实现只有方法签名
变量可以有实例变量只能有常量
继承单继承多实现
用途复用代码定义契约

何时使用抽象?

  • ✅ 定义通用接口(如 ShapeAnimal

  • ✅ 隐藏复杂实现细节

  • ✅ 强制子类实现特定方法


四、OOP 的进阶概念

5. 类与对象 (Class vs Object)

核心区别:类是模板,对象是实例

现实类比

类 = 饼干模具 对象 = 用模具做出的饼干

一个模具可以做出很多饼干 但每个饼干都是独立的个体

代码示例

// 类(模板) class User { constructor(name, email) { this.name = name; this.email = email; }

sayHello() {
    console.log(`你好,我是${this.name}`);
}

}

// 对象(实例) const user1 = new User(“张三”, “zhangsan@example.com”); const user2 = new User(“李四”, “lisi@example.com”);

user1.sayHello(); // 你好,我是张三 user2.sayHello(); // 你好,我是李四

console.log(user1 === user2); // false(两个不同的对象)

关键要点

  • 类定义了对象的属性和方法

  • 对象是类的具体实例

  • 一个类可以创建多个对象

  • 每个对象有独立的状态


6. 方法 (Methods)

核心思想:对象的行为

方法 vs 函数

维度方法函数
归属属于类/对象独立存在
访问可以访问私有成员只能访问参数
调用object.method()function()

方法的类型

class Calculator: # 实例方法(最常用) def add(self, a, b): return a + b

# 类方法(操作类本身)
@classmethod
def get_info(cls):
    return f"This is a {cls.__name__}"

# 静态方法(与类无关的工具函数)
@staticmethod
def multiply(a, b):
    return a * b

# 魔术方法(重载运算符)
def __call__(self, x):
    return x * 2

calc = Calculator() print(calc.add(1, 2)) # 实例方法 print(Calculator.get_info()) # 类方法 print(Calculator.multiply(3, 4)) # 静态方法 print(calc(5)) # 魔术方法,输出10

最佳实践

  • ✅ 方法名应该是动词(calculateTotal()sendEmail()

  • ✅ 一个方法只做一件事

  • ✅ 方法参数不超过5个


7. 消息传递 (Message Passing)

核心思想:对象通过调用方法来”通信”

现实类比

你(对象A)想点外卖 ↓ 发送消息:call(外卖小哥) ↓ 外卖小哥(对象B)收到消息 ↓ 执行动作:deliverFood()

代码示例

class OrderProcessor def process_order(order) # 发送消息给库存系统 inventory = InventorySystem.new inventory.check_stock(order.items)

# 发送消息给支付系统
payment = PaymentSystem.new
payment.charge(order.customer, order.total)

# 发送消息给物流系统
shipping = ShippingSystem.new
shipping.schedule_delivery(order.address)

end end

每个系统是独立的对象

它们通过”消息传递”来协作

不需要知道其他对象的内部实现

消息传递的好处

  • 解耦:对象之间低耦合

  • 灵活性:可以替换消息接收者

  • 并发:消息可以异步处理


8. 组合 (Composition)

核心思想:通过组合其他对象来构建复杂对象

组合 vs 继承

继承(is-a 关系): 狗 is-an 动物 ✅ 猫 is-an 动物 ✅ 汽车 is-an 引擎 ❌ (不对!)

组合(has-a 关系): 汽车 has-an 引擎 ✅ 汽车 has-four 轮胎 ✅ 计算机 has-a CPU ✅

代码示例

❌ 滥用继承

class Car: def start(self): print(“汽车启动”)

class Engine: def ignite(self): print(“引擎点火”)

汽车继承引擎?不对!

class SportsCar(Car, Engine): # 多重继承,复杂 pass

✅ 使用组合

class Engine: def ignite(self): print(“引擎点火”)

class Wheel: def rotate(self): print(“轮胎转动”)

class Car: def init(self): self.engine = Engine() # 组合:汽车”有”一个引擎 self.wheels = [Wheel() for _ in range(4)] # 组合:汽车”有”四个轮胎

def start(self):
    self.engine.ignite()
    for wheel in self.wheels:
        wheel.rotate()
    print("汽车启动")

组合的优势

  • 灵活性:可以在运行时更换组件

  • 避免继承爆炸:不需要多层继承

  • 更符合现实:大部分关系是”has-a”而非”is-a”

最佳实践

优先使用组合,而非继承(Favor Composition over Inheritance)


五、OOP 设计原则(SOLID)

在掌握了8个核心概念后,还需要遵循5大设计原则:

原则全称含义
SSingle Responsibility一个类只做一件事
OOpen/Closed对扩展开放,对修改关闭
LLiskov Substitution子类可以替换父类
IInterface Segregation接口要小而专
DDependency Inversion依赖抽象,不依赖具体

代码示例(违反SOLID vs 遵循SOLID)

❌ 违反单一职责原则

class User: def save_to_database(self): pass

def send_email(self):
    pass

def generate_report(self):
    pass

一个类做了太多事情!

✅ 遵循单一职责原则

class User: def init(self, name, email): self.name = name self.email = email

class UserRepository: def save(self, user): pass

class EmailService: def send(self, to, subject, body): pass

class ReportGenerator: def generate(self, user): pass


六、实战案例:电商系统

让我们用一个完整的电商系统来综合运用8个概念:

1. 抽象:定义支付接口

from abc import ABC, abstractmethod

class Payment(ABC): @abstractmethod def pay(self, amount): pass

2. 继承:具体支付方式

class CreditCardPayment(Payment): def pay(self, amount): print(f”信用卡支付 ¥{amount}”)

class WeChatPayment(Payment): def pay(self, amount): print(f”微信支付 ¥{amount}“)

3. 封装:订单类

class Order: def init(self, items): self.__items = items # 私有变量 self.__status = “pending”

def add_item(self, item):
    self.__items.append(item)

def get_total(self):
    return sum(item['price'] for item in self.__items)

def process_payment(self, payment_method):
    # 4\. 多态:运行时决定支付方式
    payment_method.pay(self.get_total())
    self.__status = "paid"

def __str__(self):
    return f"订单状态: {self.__status}, 总额: ¥{self.get_total()}"

5. 组合:购物车

class ShoppingCart: def init(self): self.items = []

def add(self, product, quantity):
    self.items.append({
        'product': product,
        'quantity': quantity,
        'price': product.price * quantity
    })

def checkout(self, payment_method):
    order = Order(self.items)
    order.process_payment(payment_method)
    return order

6. 类与对象

class Product: def init(self, name, price): self.name = name self.price = price

7. 方法

class Customer: def init(self, name): self.name = name self.cart = ShoppingCart()

def add_to_cart(self, product, quantity):
    self.cart.add(product, quantity)

def checkout(self, payment_method):
    return self.cart.checkout(payment_method)

8. 消息传递

class NotificationService: def send_confirmation(self, customer, order): print(f”发送通知给 {customer.name}: {order}“)

使用

product = Product(“iPhone”, 5999) customer = Customer(“张三”) customer.add_to_cart(product, 1)

payment = WeChatPayment() order = customer.checkout(payment)

notification = NotificationService() notification.send_confirmation(customer, order)

输出

微信支付 ¥5999 发送通知给 张三: 订单状态: paid, 总额: ¥5999


七、OOP 的陷阱与最佳实践

⚠️ 常见陷阱

陷阱表现解决方案
上帝类一个类做了太多事拆分成多个小类
贫血模型类只有数据没有行为将业务逻辑移入类内
过度继承继承层次过深使用组合替代
循环依赖A依赖B,B依赖A引入中间层

✅ 最佳实践

  1. 类名应该是名词UserOrderPayment

  2. 方法名应该是动词calculateTotal()sendEmail()

  3. 一个类只做一件事:单一职责原则

  4. 优先使用组合:而不是继承

  5. 保持类的简单:不超过200行代码


八、OOP 在现代编程中的演变

传统 OOP(Java、C++)

类定义 → 实例化对象 → 调用方法

函数式编程 + OOP(现代趋势)

// JavaScript: 函数式 + 面向对象 class UserService { async getUsers() { const response = await fetch(‘/api/users’); return response.json(); } }

// 或使用函数式写法 const getUsers = async () => { const response = await fetch(‘/api/users’); return response.json(); };

OOP 的未来

  • 数据导向设计(Data-Oriented Design)

  • 组件化架构(React、Vue)

  • Actor模型(并发编程)


九、总结

OOP 的8个核心概念

概念作用关键词
类与对象模板 vs 实例模板化
封装隐藏细节安全性
继承复用代码重用性
多态同一接口,不同实现灵活性
抽象简化复杂度易用性
方法对象的行为操作
消息传递对象间通信解耦
组合构建复杂对象模块化

记住:OOP 不是目的,而是手段。

真正的目标是:

  • 📦 组织代码:让代码结构清晰

  • 🔧 易于维护:修改一处不影响全局

  • 🚀 便于扩展:添加新功能不破坏旧代码

最后建议

不要害怕OOP,把它想象成创建数字乐高积木。看书、看教程,然后多写代码——没有比练习更好的学习方法了!

掌握这些概念,你就能从写简单的脚本,进阶到开发复杂的软件系统!