网站首页 > 文章精选 正文
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它通过对象来模拟现实世界的实体和逻辑。就像用乐高积木搭建模型一样,OOP通过组合不同的"代码积木"来构建程序。
在VBA中实现面向对象编程(OOP)虽然功能有限,但通过类模块、属性、方法、事件和接口等特性,仍能有效组织代码。以下是VBA面向对象编程的核心要点及示例。
用Excel工作簿理解OOP的三大核心
1对象(Object)
是什么:具体存在的"东西"
就像Excel中的一个工作簿、一个工作表、一个单元格区域
每个对象都有自己独特的属性和行为
' 创建一个具体的"单元格"对象
Dim 我的单元格 As Range
Set 我的单元格 = Worksheets("Sheet1").Range("A1")
2类(Class)
是什么:对象的"设计图纸"
类定义了对象的结构(属性+方法)
在VBA中对应类模块(Class Module)
' 类模块:cls员工
Private p姓名 As String ' 属性
Private p工资 As Currency
Public Sub 调薪(比例 As Double) ' 方法
p工资 = p工资 * (1 + 比例)
End Sub
3三大特征
特征 | 说明 | VBA示例 |
封装 | 隐藏内部细节,暴露安全接口 | 用Property Let/Get控制数据访问 |
继承 | VBA不支持直接继承,但可通过接口模拟 | 使用Implements实现多接口 |
多态 | 同一操作作用于不同对象产生不同结果 | 接口类统一调用不同实现 |
为什么需要面向对象?
1真实案例对比
传统写法:散落各处的数据和逻辑
Sub 处理订单()
Dim 订单号 As String
Dim 金额 As Double
' ...混杂的数据处理...
End Sub
OOP写法:高度组织化的结构
Dim 订单 As New cls订单
订单.编号 = "DD202307001"
订单.添加商品 "手机", 2
订单.计算总价
2核心优势
- 复用性:像搭积木一样复用类
- 扩展性:新增功能不影响旧代码
- 维护性:问题定位更精准(如只修改cls订单类)
- 可靠性:通过封装防止数据误操作
一、从乐高积木理解面向对象
积木世界模型:
- 设计图纸(类) → 定义积木形状和连接点
- 实体积木(对象) → 根据图纸生产的可操作部件
- 组合继承(继承) → 在基础积木上添加新功能
- 标准接口(多态) → 不同积木的通用连接方式
VBA建造口诀:
"先画图纸再生产,封装特性定接口,继承扩展功能,多态统一调用"
二、四大建造法则
2.1 封装:保险箱原则
' clsBankAccount 类模块
Private pBalance As Currency
Public Property Get Balance() As Currency
Balance = pBalance
End Property
Public Sub Deposit(金额 As Currency)
If 金额 > 0 Then pBalance = pBalance + 金额
End Sub
Public Sub Withdraw(金额 As Currency)
If 金额 <= pBalance Then pBalance = pBalance - 金额
End Sub
外部只能通过Deposit/Withdraw操作余额,无法直接修改pBalance
2.2 继承:升级套件方案(VBA通过接口模拟)
' IShape 类模块(接口)
Public Sub Draw()
End Sub
' clsCircle 实现接口
Implements IShape
Private Sub IShape_Draw()
' 绘制圆形代码
End Sub
' clsSquare 实现接口
Implements IShape
Private Sub IShape_Draw()
' 绘制方形代码
End Sub
2.3 多态:万能遥控器
Sub 绘制所有图形(图形集合 As Collection)
Dim 图形 As IShape
For Each 图形 In 图形集合
图形.Draw
Next
End Sub
2.4 抽象:概念设计图
' clsAnimal 抽象类
Public Sub Speak()
Err.Raise 1001, , "必须实现具体动物的叫声"
End Sub
' clsDog 继承类
Public Sub Speak()
Debug.Print "汪汪!"
End Sub
三、VBA面向对象三大实践
3.1 创建业务对象模型
' clsOrder 订单类
Private pItems As Collection
Public Sub AddItem(产品 As clsProduct, 数量 As Integer)
pItems.Add Array(产品, 数量)
End Sub
Public Function 总价() As Currency
Dim 单项 As Variant
For Each 单项 In pItems
总价 = 总价 + 单项(0).价格 * 单项(1)
Next
End Function
3.2 实现观察者模式
' clsSubject 被观察者
Private 观察者们 As New Collection
Public Sub 添加观察者(观察者 As IObserver)
观察者们.Add 观察者
End Sub
Private Sub 通知()
Dim obs As IObserver
For Each obs In 观察者们
obs.更新 Me
Next
End Sub
3.3 构建工厂模式
Public Function 创建报表(类型 As String) As IReport
Select Case 类型
Case "销售": Set 创建报表 = New cls销售报表
Case "库存": Set 创建报表 = New cls库存报表
Case Else: Err.Raise 1002, , "不支持的报表类型"
End Select
End Function
四、VBA面向对象特性表
特性 | VBA支持情况 | 替代方案 | 应用场景 |
封装 | 完整支持 | 类模块+属性 | 数据保护 |
继承 | 不支持 | 接口+组合 | 功能扩展 |
多态 | 接口实现 | 接口类 | 统一调用 |
抽象类 | 部分模拟 | 抛出错误强制重写 | 规范设计 |
五、实战案例
案例1:智能单元格格式器
' clsCellFormatter 类
Public Sub 格式化(范围 As Range)
With 范围
.Font.Name = "微软雅黑"
.Borders.LineStyle = xlContinuous
End With
End Sub
' 使用继承创建货币格式器
Implements IFormatter
Private Sub IFormatter_格式化(范围 As Range)
MyBase.格式化 范围
范围.NumberFormat = "$#,##0.00"
End Sub
案例2:自动化报表生成系统
Dim 报表引擎 As New cls报表工厂
Set 销售报表 = 报表引擎.创建报表("销售")
销售报表.设置数据源 Range("A1:G100")
销售报表.生成PDF
六、避坑指南
6.1 对象生命周期管理
Set 订单 = New clsOrder ' 创建对象
' ...使用对象...
Set 订单 = Nothing ' 必须手动释放内存
6.2 接口实现规范
' 错误:忘记Implments语句
Implements IShape ' 必须声明实现的接口
' 错误:签名不一致
Private Sub IShape_Draw() ' 必须完全匹配接口定义
6.3 循环引用破解法
' 类A引用类B,类B又引用类A时:
- 抽象出公共接口模块
- 使用事件机制代替直接调用
- 引入中介者类协调交互
七、调试
7.1 对象监视技巧
- 在类模块中插入Debug.Print
- 使用立即窗口检查对象状态:
Set emp = New clsEmployee
emp.姓名 = "测试"
?emp.工龄
7.2 接口验证工具
Sub 检查实现(实例 As Object, 接口 As String)
If TypeOf 实例 Is 接口 Then
Debug.Print "正确实现接口"
Else
Debug.Print "接口实现不完整"
End If
End Sub
下章预告:《正则表达式》
猜你喜欢
- 2025-06-03 2、Java面向对象编程思想(超详细)
- 2025-06-03 信息系统项目管理师综合知识:面向对象方法
- 2025-06-03 canvas学习和面向对象(二)(canvas详解)
- 2025-06-03 python进阶突破面向对象——四大支柱
- 2025-06-03 Swift 面向对象解析(一)(swift 面向协议编程)
- 2025-06-03 简述JS面向对象编程(个人理解,简易版)
- 2025-06-03 软考系规:面向对象系统分析与设计详解
- 2025-06-03 Python基础篇-面向对象编程(python 面向对象知乎)
- 2025-06-03 此继承非彼继承,今天说的是面向对象的基本特征之一
- 2025-06-03 一张图深入解析面向对象常见概念,秒懂
- 最近发表
-
- 面试中常被问到的Hash表,你了解吗
- JAVA面试考点:一文搞懂一致性Hash的原理和实现
- 一次性搞清楚equals和hashCode(hashcode() 与equals()区别,简单说明)
- HashMap.Key的故事:Key为什么出现Hash碰撞及冲突呢?
- hash冲突的几种解决方案对比(hash冲突的解决方式)
- 游戏王LN 无头骑士(无头骑士cv)
- Linux ln、unlink命令用法(linux link命令详解)
- n和l分不清矫正发音方法,这三步就够了
- golang引用私有gitlab项目代码(golang引入当前包下的文件)
- Instamic:录音领域中的 GoPro,让你想录就录,随心所欲
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)