1、第三章 面向对象技术,软件技术基础,面向对象(Object Oriented)的基本概念,什么是对象(Object)? 什么是类(Class) 类和对象区别与联系,什么是对象?,“对象”是事物 对象有一个身份,该身份用属性定义 对象还可以做事情,对象所能做的事情称为对象的行为 对象可以是真实世界的事物,也可以是概念性的事物,什么是类,将事物分类进行研究,是人类常用的一种思维方式。 类通过设定该类中每个对象将具有的属性和行为来提供对象的定义。,类和对象区别与联系,对象之间的关系,对象的三种基本关系(relationship)依赖(dependency)关系泛化(generalization 继承
2、、父子)关系关联(association)关系,依赖关系,依赖(Dependency)是一种使用关系,它描述了一个对象的规格说明的变化可能会影响到使用它的另一个对象,但反之不然。,泛化关系,天花病毒,流感病毒,SARS病毒,病毒,RNA 复制 侵害肌体 传染性 疫苗,泛化(Generalization)描述了一般对象和较特殊的对象之间的关系。,关联关系,关联(Dependency)是一种结构关系,它描述了一个对象与另一个对象相联系,面向对象系统的基本元素,抽象(Abstraction) 封装(Encapsulation) 继承(Inheritance) 多态(Polymorphism),抽象(
3、Abstraction),过滤掉对象的一部分特性和操作直到只剩下你所需要的属性和操作。,通过抽象,可以将精力集中在应用程序对象上而不是 实现上。使用户和领域专家能够真正参与到设计中来,关注重点,封装(Encapsulation),当一个对象执行自己的操作时,它对外界隐藏了操作的细节。,接口(Interface)对象总要提供一个“接口”与外部世界建立联系,封装通过隐藏对象的内部实现来帮助抽象,即可以使用一个对象而不必理解对象类是如何实现的,隐藏私有,继承(Inheritance),通过使用继承性可以消除冗余属性和行为并获得再利用。 两类基本的继承:实现继承,属于子类的任意对象自动再利用父类的全部
4、属性和行为(VB6.0以下版本不支持)接口继承,提供了一个接口(属性、行为)的再利用,允许这些属性和行为以不同的方式实现(VB6.0支持),再利用,多态(Polymorphism),两个或多个类可以有名字相同、基本目的相同但实现方式不同的行为VB6利用公共接口来实现多态,同名行为,不同实现,思考,对汽车思考面向对象的概念(抽象、封装、继承、多态各举一例) 考虑过去是如何分析和设计程序的,试着用对象和类去具体化你的一个应用程序 考察在食堂打饭的过程(用饭卡),描述相关对象的属性和行为,以及这些对象之间的关系,VB6语言面向对象的特征(一),在类模块中定义类 用Property过程提供公共访问 定
5、义多态性方法 生成事件 封装类常量 用Object Browser浏览类 创建对象,VB6语言面向对象的特征(二),将窗体用作对象 使用多组对象 定义多个接口 用ActiveX组件说明对象 开发基于Web的应用程序 创建C/S应用程序,VB6中类与集合的应用,创建一个类 使用一个类的实例 窗体类的使用 定义类中的常量 生成和响应事件 定义集合 使用集合,创建一个类,插入一个类模块 定义类的属性 创建类的方法 响应类事件 文档化类,插入一个类模块,启动一个新的工程 从工程菜单选择添加类模块 设定类名称,窗体也是一个类 工具箱中的控件也是一个类,定义类的属性 类属性定义由一个类创建的全部对象的属性
6、,声明一个公共变量简单数据类型(Integer、String)抽象类型(Object)用户定义的类型(UDT)不能定义为公共变量最简单,不推荐使用 先声明一个私有变量,然后创建Property过程以显露属性Property过程允许一个类中的属性被声明为私有变量并由公共过程显露,创建Property(一),声明一个私有变量Private mvar*注意是 Private 而不是Dim只有类内部的过程可以更改变量值,对应用程序的其它部分隐藏 创建Property过程Property Get 获取或读入属性值Property Let 设置String、Integer等简单数据类型的属性值Proper
7、ty Set 设置对象数据类型的属性值,创建Property(二),多数情况下,类的每个属性有一对Property过程 Private mvarDescription As String Public Property Let Description(ByVal vData As String)向属性指派值时使用,位于赋值语句的左边。Syntax: X.Description = 5mvarDescription = vData End PropertyPublic Property Get Description() As String检索属性值时使用,位于赋值语句的右边。Syntax: D
8、ebug.Print X.DescriptionDescription = mvarDescription End Property,创建Property(二),只使用Property Get限制属性为只读 只使用Property Let或Property Set限制属性为只写 Property过程可以包含有效性验证、格式化或其它处理过程 Friend Property Let Priority(ByVal vData As Integer)if vData4 thenvData=0end ifmvarPriority = vData End Property Friend Property
9、Get Priority() As IntegerPriority = mvarPriority End Property,使用Property的益处,封装格式化、数据有效性或其它处理过程 只读 维护可以只更改Property过程的代码而不更改使用该属性的代码,创建方法 类方法定义由一个类创建的全部对象的方法,Private方法在类的内部访问 Public方法在类的外部访问返回值Function不返回值Sub 类方法按正常的Sub或Function过程实现,响应事件,两个内置响应事件 Initialize提供了执行由类创建的对象初始化的机会 Terminate提供了执行任何清除处理的场所,In
10、itialize,当由一个类创建对象时,就触发了Initialize事件,所以可用于是首批代码的执行 Private Sub Class_Initialize()InitA为只读属性,将初始值设为1mvarInitA = 1MsgBox “A的初始值“ & InitA End Sub,Terminate,当释放一个对象时,触发Terminate事件可以向Terminate事件中添加代码以解除与此对象相关联的相关对象,或在对象被破坏时应该执行的过程Private Sub Class_Terminate()MsgBox “对象被释放“ End Sub,文档化类,从“工具”菜单中选择 “过程属性”从
11、“工程”菜单中选择 “添加文件”,使用对象浏览器,创建和使用一个类实例(对象),声明对象变量 创建对象 使用对象属性和方法 释放对象,声明对象变量,声明一个数据类型为对象类的变量Private m_Xq as CStudent 使用New关键字声明一个数据类型为对象类的变量Private m_Xq as new CStudent 利用定义为对象的数据类型去声明一个变量Private m_Xq as Object,创建对象,通过使用带有New关键字的Set语句显式地创建对象set m_Xq = new CStudent 通过使用对象而隐式地创建对象m_Xq.Study 通过使用CreateObj
12、ect函数创建对象,设定、获取对象属性,举例说明,释放对象的引用,Set Xobject=Nothing,定义类中的常量,避免幻数 定义局部常量(Const) 使用Enum语句(枚举变量 ) 定义全局长整型常量 定义字符串常量,集合,集合提供了一种把一组相关的对象和一个“包含”它们的对象连接起来的方法 集合本身是一个对象,并由类来创建,该类称为集合类 通过将私有的集合对象包装到类模块中,可实现部件的对象模型的集合,这样就定义了一个集合类,Collection 对象示例,声明Collection对象 Count 属性 Add 方法添加成员 Remove 方法删除成员 Item 方法返回特定成员
13、For Each.Next枚举集合 举例,在VB6.0中创建集合类,在类模块中定义类 (CStudents) 创建集合对象实例 向集合类中添加属性和方法 使用集合类,创建集合对象实例,Private mColStudents As CollectionPrivate Sub Class_Initialize()创建集合对象Set mColStudents = New Collection End SubPrivate Sub Class_Terminate()Set mColStudents = Nothing End Sub,集合类中添加属性和方法,与Collection类似,集合类必须提供
14、添加( Add )、删除(Remove)成员以及返回(Item)特定成员的功能,Add方法,Public Function Add(StudentName As String, Sex As Integer, Optional sKey As String) As Student创建新对象Dim objNewMember As StudentSet objNewMember = New Student设置传入方法的属性objNewMember.StudentName = StudentNameobjNewMember.Sex = SexIf Len(sKey) = 0 ThenmColStud
15、ents.Add objNewMemberElsemColStudents.Add objNewMember, sKeyEnd If返回已创建的对象Set Add = objNewMemberSet objNewMember = Nothing End Function,Remove方法,Public Sub Remove(vntIndexKey As Variant)删除集合中的元素时使用。vntIndexKey 包含索引或关键字,这是为什么要声明为 Variant 的原因语法:x.Remove(xyz)mColStudents.Remove vntIndexKey End Sub,Item
16、方法,Public Property Get Item(vntIndexKey As Variant) As CStudent引用集合中的一个元素时使用。vntIndexKey 包含集合的索引或关键字,这是为什么要声明为 Variant 的原因语法:Set foo = x.Item(xyz) or Set foo = x.Item(5)Set Item = mColStudents(vntIndexKey) End Property,使 For Each . Next 有效,NewEnum 必须返回一个集合的枚举算子的 IUnknown 接口。 Public Function NewEnum(
17、) As IUnknown Set NewEnum = mcolEmployees._NewEnum End Function 委派给 Collection 对象的最重要的东西是它的枚举算子。枚举算子是一个小对象,该对象知道如何遍历集合中的各项。不能用 Visual Basic 来书写枚举算子对象,因为 Employees 类是基于 Collection 对象的,可以返回 Collection 对象的枚举算子它自然知道如何枚举 Collection 对象所保存的各项。 包围 Collection 对象的 _NewEnum 方法的方括号是必要的,这是因为方法名前面的下划线。前面的这个下划线是一个
18、约定,它指明该方法是隐藏在类型库中的。不能把自己的方法命名为 _NewEnum,但是可以把它隐藏在类型库中,并将 For Each . Next 所需要的过程 ID 赋给它。,隐藏 NewEnum,在“工具”菜单上,单击“过程属性”,打开“过程属性”对话框,在“名称”框中,选择 NewEnum 方法。 单击“高级”,显示一些高级功能。选中“隐藏该成员”,使 NewEnum 隐藏在类型库中。 在“过程标识符”框中,键入 -4,将 For Each . Next 所需要的过程标识符赋给 NewEnum。单击“确定”。,其它,Public Property Get Count() As Long检索
19、集合中的元素数时使用。语法:Debug.Print x.CountCount = mColStudents.Count End Property Public Sub Clear()Set mColStudents = New Collection End Sub,利用类生成器构建集合类,手工建立繁琐首先利用类生成器构建类然后利用类生成器构建集合类,作业,利用集合类创建学生成绩信息输入程序,并成批保存到数据库中,接口,接口就是一些属性、方法和事件的集合 单独的Customer类可以定义公共属性和方法(复杂) 将对象的功能分为被称为接口的逻辑集 一个例程随后可以使用这些接口并确保它只使用该接口正
20、确的属性和方法,SendTo SendFrom Message Send Delete,Fax Number Transmit,Phone Number Call,Name Address Buy,IDefault,IPhone,IFax,IEmail,Customer,Name Address Buy Phone Number Call Fax Number Transmit SendTo SendFrom Message Send Delete,使用接口的益处,简化开发在一个大型程序中,一个类可以有很多不同的属性和方法以提供特定类型的功能。如果属性和方法组合到接口中,类的开发就被简化了。
21、一组类中的标准功能一个接口提供了一组预定义的属性和方法 简化的再利用可以在任意数量的类中实现一个接口,如果以后想在不同的类中定义同一组属性和方法,可以通过在其它类中实现接口来再利用,使用接口的益处,添加了新功能但不影响已有的接口如何向Customer中增加Mobile功能?1、更改IPhone接口 2、添加新接口IMobile 思考:软件是如何升级的? 改善的多态性实现统一接口的多重类一般可以通过使用多态性的接口进行访问 获得实现继承性为了防止多个类中代码的重复,可以在单个类中开发公共的代码,该类称为基类,可通过引用每个类中的基类的接口实现继承,创建并实现接口,使用VB6创建接口使用新的Imp
22、lements关键字实现接口使用替代接口,VB6创建接口,添加一个类 (Isave) 添加空的方法(Save),模块级变量声明和过程代码?,在一个用作接口的类模块中的代码,包括定义的私有变量和事件,当实现接口时将被忽略,接口就是代表接口封装的成员(方法以及属性)的原型集合;也就是说,它只包含成员过程的声明部分 。,Implements语句,指定要在包含该语句的类模块中实现的接口或类Implements InterfaceName | Class Implements 语句不能在标准模块中使用,实现接口,同一接口可以在应用程序中的任意数量的窗体或类模块(不含标准模块)中实现用Implements
23、语句声明接口从”对象”框中选择接口,从 “过程/事件”框中选择属性和方法添加代码以实现接口,使用接口,将对象分配给接口声明带有接口变量的过程,将对象分配给接口,声明对象变量Private mCustomer as CCustomer 声明接口类型变量Private mIsave as Isave 将接口对象赋给对象变量set mCustomer = New CCustomerset mIsave = mCustomer 不要New 使用接口变量引发属性或方法mIsave.save,声明带有接口变量的过程,声明对象变量Private mCustomer as CCustomer 创建过程以实现该
24、操作public sub save(Obj as Isave)if obj.isdirty thenobj.saveend ifend sub 调用过程并将对象作为变量传递save mCustomer,用接口实现多态性,多态性就是利用公共接口与来自不同类的对象交流的能力 实现多态性多重类可以实现同一接口,该接口中所定义的属性和方法随后可以被引发,以作用于由实现接口的类所创建的任意对象。Private mCustomer as CCustomerPrivate mStudent as CStudentsave mStudentsave mCustomer,集合多态性的实现,可以使用同集合相结合的
25、多态性来引发集合中全部对象的属性或方法。For each obj in mcolObjectsif obj.isdirty thenobj.saveend if next,VB6实现继承性,继承性就是在类中实现功能再利用的能力 基类定义了公共功能,子类继承了该功能并可按需添加功能 VB6可实现接口继承性而不支持实现继承性,VB6中通过接口获得继承性的方法,创建基类 实现子类中的基类 声明子类中基类的对象变量 由基类创建对象 授权给基类,创建基类Cperson,添加类模块Cperson声明基类的属性和方法在基类的属性和方法中添加公共代码,实现基类,在子类(Cstudent)中声明接口(Imple
26、ments Cperson) 在子类中调用基类的属性和方法模板,Save,Name Sex,ID,IDefault,CStudent,Cperson,ISave,创建基类的对象变量,在给基类授权前,需要创建一个基类对象 首先声明一个基类对象变量 在子类Initialize事件中创建对象 在子类Terminate事件中释放对象,给基类授权,调用另一个例程以实现一个操作的过程称为授权 属性的授权 Private Property Get CPerson_Name() As StringCPerson_Name = mvarPerson.Name End Property Private Property Let CPerson_Name(ByVal RHS As String)mvarPerson.Name = RHS End Property 方法的授权 Private Function CPerson_Work() As BooleanCPerson_Work = mvarPerson.WorkMsgBox “I am studing!“ End Function,使用基类接口,举例说明,