ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 11692|回复: 21

[原创] 类的学习笔记与讲解

[复制链接]

TA的精华主题

TA的得分主题

发表于 2012-5-6 10:15 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:类和类模块
序:学习VBA快一年了,深感对于初学者很多教程都是模块化讲解,也就是假定这一章讲的是循环,然后假定你看完后,对所有其他章节的循环你都掌握了,事实是,我们还不一定掌握,为什么?从心理学的角度来说,前后几章的例子不连续,知识没有承上启下的联系,导致新的情景产生后影响对循环这个知识点的理解。我一直想写一个教程,换个角度给初学者讲解下VBA,陆续写了两三章了,自己感觉通俗易懂,只是自己感觉而已,所以我想先在论坛上发发,看看大家的意见。

最后,我认为学习对概念的理解不一定要准确的,在构建一个概念之前,我们每个人都会有一个模型去套,去凑,去尽量接近这部分真理,也就是建构主义的方式。我本人是心理学专业的,所以对学习的过程感知更加细腻点。欢迎大家去百度什么叫建构主义。讲了这么多,其实我的意思是:就像初中数学知识和高中数学知识一样,初中的时候一般不会讲到复数,对负数开根号是没有意义的。因为我们初中时候学的知识就是说,数是实数,负数开根号没意义。我为了补充自己的类模块知识,写了以下教程给初学者,当然我还写了很多,希望大家提出意见,我一定写一系列依照这种风格的教程。


评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 10:16 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
类模块
类模块就是类 + 模块的含义(这不是废话吗?),其实不是,为了区分事物产生了名字。
事实是,我们前面几章讲的大部分是叫做标准模块。
上图:


如图看到了吗,我们习惯了模块,在模块下面出现了类模块。因为模块包括标准模块和类模块,所以严格意义上讲,模块省略了标准2个字,笔者觉得不是很恰当的。

那么什么是类模块?
凭空出现一个类模块,它必定有它的用处,不然VBA引入类模块做啥?
先来解释下类的含义,类就是物以类聚的类,是不是有点晕?那么让我们从一个问题开始吧,请问:
鱼和泥鳅有什么区别?
(参考http://readthedocs.org/docs/learn-python-the-hard-way-zh_cn-translation/en/latest/ex45.html)

确实鱼是鱼,泥鳅是泥鳅,泥鳅是鱼,鱼不是泥鳅,鱼儿有很多种,泥鳅是鱼儿的一种。
哦,你说,这就是类别与个体的关系!是的,没错,类就是种类。


但是隐喻虽然好理解,对与真正的代码上的类,和现实中还是有差异的,毕竟现实中是真实的生物呢!所以我们只是抽象出来类,把类看做属性和动作的合体。确实,现实中,鱼儿有颜色,大小等,这就是属性,会游泳会冒泡泡,这就是动作。对应到VBA中就是我们用变量存储属性,用函数代表动作。
好吧,VBA中的类是具有变量和函数(包括过程)的怪胎。说他是怪胎是因为我们见的少,我们见的最多的是定义一个变量,然后定义一个函数,这个变量和函数是不同,离散的,两码事对吧?但是类却“绑定”了变量和函数。好吧,从理解的角度定义(不犯罪吧?):类就是有函数又有变量的一个模板。



讲完概念接下来本该讲好处,不过,从学习的角度讲,还是先来几个例子吧,好处自然会豁然开朗。

现在我们来定义鱼儿的类





这一步做完后,开始写代码

哦,忘记了一件事,顺便讲一下,注意细节是对VBA的理解大有好处的,所谓细节我的理解就是,标点符号,各种图标,各种稀奇古怪你还不了解的菜单名称,在代码编辑以及实际编程实践中,这种细节很重要,虽然我们不能一下子完全理解,但是先在大脑中有个疑问是比较好的一种学习方法。
讲了这么多,其实想让大家注意这样一个差别:
看到模块与类模块的图标有差异吧。一个是乱七八糟像星星,一个是井然有序的三角形,从这一角度再一次理解成,模块是离散的函数与变量,而类是集变量和函数(属性和动作)于一体。

ok,插入了类模块
取个名字叫fish





Public Name As String
Public Color  As String
Public Function Swim(Distance As Integer)
  Swim = Distance
End Function

在标准模块中写入如下代码:

Sub Fishforfun()
  Dim goldFish As fish
  Set goldFish = New fish
  goldFish.Color = "Gold Yellow" '哈哈,我不知道金黄色怎么说
  goldFish.Name = "Goldfish"
  MsgBox "定义一条:" & goldFish.Name & vbCrLf & "颜色当然是:" & goldFish.Color & vbCrLf _
      & "它向前游了" & goldFish.Swim(50) & "米"
End Sub

运行结果:

点评

支持楼主!  发表于 2012-5-6 10:21

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 10:26 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 12:01 | 显示全部楼层
本来想继续把这个例子创作下去,但是发现原创例子很难,一是金鱼和现实中联系的少,二是即使创作下去,也不实用。所以我借用了几本书上的例子:
电子书 :《Excel.2007.VBA.Programmers.Reference》翻译的书名是《Excel.2007.VBA参考大全》
实体书:《Microsoft Excel 2010 Programming by Example: With VBA, XML, and ASP 》暂无中文版
电子书:《Definitive Guide to Excel VBA, Second Edition》
电子书: 《VBA Developer's Handbook, 2nd 》
实体书:《Excel 2010 Power Programming with VBA 》中文版

所以我应该调整次序,把简单的例子放到前面,不过,先这样了吧,下次调整。
ok,既然大家都喜欢用史上,全球等这么有爆发力的词汇,我从 Definitive Guide to Excel VBA, Second Edition找了一个全宇宙最简单的类的例子,它只有属性,没法方法(也就是没有动作,没有函数,没有过程)
Sub XYtest()
    Dim xyP As XYpoint
    Set xyP = New XYpoint
    xyP.x = 1
    xyP.y = 9
    MsgBox "x : " & xyP.x & vbCrLf & "y : " & xyP.y
End Sub

类中只有一条语句:
Public x As Double, y As Double





Class Versus Object
类和对象
类和对象是什么差别?类是模板,对象是模板生产出来的东西。还记得鱼和泥鳅吗,鱼儿是类,说鱼是类,而泥鳅是鱼儿产生的对象?这个隐喻不好理解,那换一种吧,在《c++ Primer Plus 》中有这样的比喻,类是生产饼干的那个铁盒模具,而对象就是饼干。

TA的精华主题

TA的得分主题

发表于 2012-5-6 12:05 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 13:36 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
好的,明天上附件,今天还在写

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 14:53 | 显示全部楼层
本帖最后由 zjyivad 于 2012-5-6 15:17 编辑

哦对了,还需要解释一下的是,这两条语句把上面的例子中诸如  
    Dim xyP As XYpoint
    Set xyP = New Xypoint
合并成一条:Dim xyP  As New Xypoint
所以
Dim a As New XYPoints 等价于
Dim a as XYPoints
Set a = New XYPoints


现在是把类改装下,在改装之前我们来看看平常我们定义变量的时候:
Dim a As Integer
Let a = 100

是不是你从来不用Let的?对了,确实不需要,是省略的,因为a是一个普通的变量。于此对应一个对象变量,上面阐述过了,对象是包括变量和动作的合体,所以你不能用Let 要用Set 而且这个Set不能省略。就像模块就是代表标准模块,而类模块是类模块的意思一样,也就是模块本来是总称,现在一般指标准模块,而类模块为了区分标准模块,加了个类字。标准模块省略了标准两个字。

其实,不管是标准模块还是类模块,既然代码无论如何都写在模块中,标准模块在某种程度上也是一个类,是无需声明的无需定义的类,也就是可以直接拿来用,请看在模块2中写入如下代码:
Sub Test2()
    Call 模块1.XYtest2
End Sub

而我在模块2也有同样的过程XYtest2,读者大概也明白了,即使XYtest2在模块2中,调用的也是模块1的过程XYtest2,而非模块2的过程XYtest2,此时的模块1像不像类模块呢,而此时的XYtest2是不是类模块的动作呢?
虽然可以认为这只是简单的调用函数,也就是调用了模块1的XYtest2过程而已,但是从类的角度来看,这种行为也类似于调用类的动作(也即类的方法)

临时的2个附件,接下去会更新附件内容:
类.rar (264.7 KB, 下载次数: 211)

TA的精华主题

TA的得分主题

发表于 2012-5-6 16:14 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 16:44 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2012-5-6 17:31 | 显示全部楼层

继续,改装XYPoints类(最早只有一条语句Public x As Double, y As Double)
这里出现了一个新的关键字Get,顾名思义就是得到的意思。Let已经出现过了,但是这里的let又有点不同,这里的Let和Get你都把它看做是函数(过程),他们的目的就是为了操作类中的变量(也就是字段)。
Public x As Double, y As Double

Property Get Xpoint() As Double
    Xpoint = x
End Property
Property Let Xpoint(xs As Double)
    x = xs
End Property

Property Get Ypoint() As Double
    Ypoint = y
End Property
Property Let Ypoint(ys As Double)
    y = ys
End Property

这里注意了,Let函数(姑且称作过程或者函数)中是是有参数的。这个参数是等号右边传递给对象内部的。
如果
Dim a as new XYPoints
a. Xpoint = 12
单步F8运行就会看到调用过程
现在我们来试一试吧
此时在下面继续添加语句
    Dim b As Double
    b = a.Xpoint
    MsgBox b
就会发现调用的是Get函数了
例子在附件中
Sub Test3()
    Dim a As New XYpoint2
    a.Xpoint = 12
    Dim b As Double
    b = a.Xpoint
    MsgBox b
End Sub



接下去我们来分析如下代码:
Sub XYtest2()
    Dim xyp As XYpoint2
    Set xyp = New XYpoint2
    xyp.Xpoint = 1
    xyp.Ypoint = 9
    MsgBox "x : " & xyp.Xpoint & vbCrLf & "y : " & xyp.Ypoint
End Sub

Sub XYtest3()
    Dim xyp As XYpoint2
    Set xyp = New XYpoint2
    xyp.x = 1
    xyp.y = 9
    MsgBox "x : " & xyp.x & vbCrLf & "y : " & xyp.y
End Sub
Xypoint2类如下:
Public x As Double, y As Double

Property Get Xpoint() As Double
    Xpoint = x
End Property
Property Let Xpoint(xs As Double)
    x = xs
End Property

Property Get Ypoint() As Double
    Ypoint = y
End Property
Property Let Ypoint(ys As Double)
    y = ys
End Property
两者运行的结果是一样的。
既然如此那搞出Let和Set是要干嘛?
我们改变下类中变量的内容:
Private x As Double, y As Double
也就是把x y设置成私有的,所以你没有办法直接访问到x和y只能通过Let和Get了。
问题是这样做有意义吗?当然有,现在不讲。只要注意到关键字从Public变成Private就够了。再次总结下,Let Get 生来没别的,是用来操作类中的变量的。类中的变量也叫做字段,
存储的是类的属性。Let和Get与字段的关系好比是媒婆,没有她们你是见不到心爱的姑娘的(除非设置成Public),因为一般美女都是Private的。
运行后弹出如下错误:


现在我们修改下XYtest4
变成:
Sub XYtest5()
    Dim xyp As XYpoint3
    Set xyp = New XYpoint3
    xyp.Xpoint = 1
    xyp.Ypoint = 9
    MsgBox "x : " & xyp.Xpoint & vbCrLf & "y : " & xyp.Ypoint
End Sub
这样就可以了
实际上从代码输入的过程中就能感知到变化:
当是Public x As Double, y As Double时候会弹出 x y字段的。
而当Private x As Double, y As Double时候就只弹出Let和Get了。




您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-4 02:52 , Processed in 0.055818 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表