'--------------------------------------------------------------------------------------- ' Module : Class1 ' Author : Anna ' Date : 2009-9-20 ' Purpose : Abstract class '---------------------------------------------------------------------------------------Option ExplicitPublic Sub M1()End Sub '--------------------------------------------------------------------------------------- ' Module : Class2 ' Author : Anna ' Date : 2009-9-20 ' Purpose : Implements Class1 '---------------------------------------------------------------------------------------Option ExplicitImplements Class1Private Sub Class1_M1() Debug.Print "Class2's implementation of Class1's M1" End SubPublic Sub M2()End Sub '--------------------------------------------------------------------------------------- ' Module : Class3 ' Author : Anna ' Date : 2009-9-20 ' Purpose : Implements Class1 and Class2 '---------------------------------------------------------------------------------------Option Explicit Implements Class1 Implements Class2Private Sub Class1_M1() Debug.Print "Class3's implementation of Class1's M1" End SubPrivate Sub Class2_M2() Debug.Print "Class3's implementation of Class2's M2" End Sub '--------------------------------------------------------------------------------------- ' Module : Module1 ' Author : Anna ' Date : 2009-9-20 ' Purpose : Test Multi-Inheritance '---------------------------------------------------------------------------------------Option ExplicitSub Test_MultiInherit() Dim aa As Class1 Dim bb As Class2 Dim cc As Class3
我感觉VB里并不支持爷孙继承,它不会了解这种隔一代的血缘关系。你看下面的例子(Class1和Class2的定义同4楼): '--------------------------------------------------------------------------------------- ' Module : Class3 ' Author : Anna ' Date : 2009-9-20 ' Purpose : Implements Class2 only '---------------------------------------------------------------------------------------Option Explicit Implements Class2Private Sub Class2_M2() Debug.Print "Class3's implementation of Class2's M2" End Sub '--------------------------------------------------------------------------------------- ' Module : Module1 ' Author : Anna ' Date : 2009-9-20 ' Purpose : Does VB know anything about Grandpa? '---------------------------------------------------------------------------------------Option ExplicitSub Test_MultiInherit() Dim aa As Class1 Dim bb As Class2 Dim cc As Class3
Set cc = New Class3
Set bb = cc Call bb.M2' Set bb = New Class2 Set aa = bb 'Type MisMatch, 除非把上一句取消注释' Call aa.M1 Set aa = Nothing Set bb = Nothing
Set cc = Nothing End Sub 上面这段代码说明,Class3能够了解自己继承自Class2,但是并不会进一步去了解Class2继承自Class1。所以你可以Set bb = cc,但是不能进一步Set aa = bb,更不能Set aa = cc。VB只能记录父类子类这样单层的继承关系。
但是Class3就不能继承Class2里的实现了。打个比方说,Class1是动物类,有个方法叫做吃(M1);Class2是哺乳动物类,Class2继承吃的方法(Class1_M1),加入自己的实现“弄死了再吃”;Class3是人,它要继承吃的方法,比较省力的办法是继承Class2的“弄死了再吃”的步骤,自己再加一个语句叫“烧熟了再吃”就可以了。可是,在VB中并不支持这样的爷孙继承。Class3如果直接继承Class2的话,它就不能继承Class2吃的方法。因为在Class2里,它继承的Class1的吃的方法是私有的(Private Sub Class1_M1)。所以,它只能直接继承Class1的M1方法,并且只好重复写上“弄死再吃”、然后加上“烧熟再吃”。
当然你可以试着把Class2里的Private Sub Class1_M1改成Public Sub Class1_M1。之后在Class3里再实现Class2的方法 Class1_M1,但是你会发现VB编译器会无法理解你的实现,因为你的实现现在叫Class2_Class1_M1,这个有二义性的名字会把VB编译器绕晕。
Implements与聚合配合是可以实现继承功能的.class1代码: Option ExplicitPublic Sub M1() Debug.Print "吃" End Sub class2代码: Option Explicit Implements Class1 Private mobjClass1 As New Class1Public Sub M1() Call mobjClass1.M1 Debug.Print "弄死再吃" End SubPrivate Sub Class1_M1() Call M1 End Sub class3代码: Option Explicit Implements Class1 Private mobjClass2 As New Class2Public Sub M1() Call mobjClass2.M1 Debug.Print "烧熟再吃" End SubPrivate Sub Class1_M1() Call M1 End Sub 窗口代码: Option ExplicitPrivate Sub Form_Load() Dim cls As New Class3 Call cls.M1 End Sub
又完善了一下:Class1代码:Option ExplicitPublic Sub M1() Debug.Print "吃" End SubClass2代码:Option Explicit Implements Class1 ' Class2实现了Class1的默认接口 Private mobjClass1 As New Class1 ' Class2聚合了Class1的一个实例' 调用基类方法,同时添加自己的内容 Public Sub M1() Call mobjClass1.M1 Debug.Print "弄死再吃" End Sub' 实现基类接口 Private Sub Class1_M1() Call M1 End SubClass3代码:Option Explicit Implements Class1 ' Class3实现了Class1的默认接口 Implements Class2 ' Class3实现了Class2的默认接口 Private mobjClass2 As New Class2 ' Class3聚合了Class2的一个实例' 调用基类方法,同时添加自己的内容 Public Sub M1() Call mobjClass2.M1 Debug.Print "烧熟再吃" End Sub' 实现基类接口 Private Sub Class1_M1() Call M1 End Sub' 实现基类接口 Private Sub Class2_M1() Call M1 End SubForm1代码:Option ExplicitPrivate Sub Form_Load() Debug.Print vbCrLf & "p3->Class3" Dim p3 As Class3 ' Class3的默认接口 Set p3 = New Class3 ' Class3对象 Call p3.M1
Debug.Print vbCrLf & "p2->Class3" Dim p2 As Class2 ' Class2接口 Set p2 = New Class3 ' Class3对象 Call p2.M1
Debug.Print vbCrLf & "p1->Class3" Dim p1 As Class1 ' Class1接口 Set p1 = New Class3 ' Class3对象 Call p1.M1
Debug.Print vbCrLf & "p2->Class2" Set p2 = New Class2 ' Class2对象 Call p2.M1
Debug.Print vbCrLf & "p1->Class2" Set p1 = New Class2 ' Class1对象 Call p1.M1
Debug.Print vbCrLf & "p1->Class1" Set p1 = New Class1 ' Class1对象 Call p1.M1 End Sub
做 QI 接口hook... 自己弄.... 多重接口继承好像是不支持.
Implements 语句 指定要在包含该语句的类模块中实现的接口或类。 语法 Implements [InterfaceName | Class] 所需的 InterfaceName 或 Class 是类型库中的接口或类的名称,该类型库中的方法将用与 Visual Basic 类中相一致的方法来实现。 说明 所谓接口就是代表接口封装的成员(方法以及属性)的原型集合;也就是说,它只包含成员过程的声明部分。一个类提供一个或多个接口的所有方法以及属性的一种实现方案。类的控制者每次调用函数时,该函数所执行的代码由类来提供。每个类至少应实现一个缺省接口。在 Visual Basic 中,一个已实现的接口中任何没有显式声明的成员都是缺省接口的隐式成员。 当 Visual Basic 类实现接口时,都会提供该接口的类型库中说明的所有 Public 过程的版本。除了提供接口原型与自编过程之间的映射关系之外,Implements 语句还使这个类接收对指定接口 ID 的 COM QueryInterface 调用。 注意 Visual Basic 不能实现派生出来的类或接口。在实现接口或类时,必须包括所用到的 Public 过程。如果在实现接口或类时遗漏了成员,就会产生错误。如果正在实现的类中某个过程还没有代码,则可以产生一个适当的错误信息 (Const E_NOTIMPL = &H80004001),以便用户意识到该成员还没有实现。
记下 Visual Basic 不能实现派生出来的类或接口。感觉也不是绝对的。
注意 Visual Basic 不能实现派生出来的类或接口。 Implements只是实现不是派生
在Class3里继承Class2里的Class1_M1(
Option Explicit Implements Class1 ' Class3实现了Class1的默认接口 Implements Class2 ' Class3实现了Class2的默认接口 Private mobjClass2 As New Class2 ' Class3聚合了Class2的一个实例
说错了,如果模拟普通函数,不是不调用,而是直接调用其模拟父类的相应函数..Class2代码: Option Explicit Implements Class1 ' Class2实现了Class1的默认接口 Private mobjClass1 As New Class1 ' Class2聚合了Class1的一个实例' 调用基类方法,同时添加自己的内容 Public Sub M1() Debug.Print "弄死再吃" End Sub' 实现基类接口 Private Sub Class1_M1() Call mobjClass1.M1 End Sub Class3代码: Option Explicit Implements Class1 ' Class3实现了Class1的默认接口 Implements Class2 ' Class3实现了Class2的默认接口 Private mobjClass2 As New Class2 ' Class3聚合了Class2的一个实例' 调用基类方法,同时添加自己的内容 Public Sub M1() Debug.Print "烧熟再吃" End Sub' 实现基类接口 Private Sub Class1_M1() Dim objClass1 As Class1 Set objClass1 = mobjClass2 Call objClass1.M1 End Sub' 实现基类接口 Private Sub Class2_M1() Call mobjClass2.M1 End Sub
Implements C1
Implements C2
' Module : Class1
' Author : Anna
' Date : 2009-9-20
' Purpose : Abstract class
'---------------------------------------------------------------------------------------Option ExplicitPublic Sub M1()End Sub
'---------------------------------------------------------------------------------------
' Module : Class2
' Author : Anna
' Date : 2009-9-20
' Purpose : Implements Class1
'---------------------------------------------------------------------------------------Option ExplicitImplements Class1Private Sub Class1_M1()
Debug.Print "Class2's implementation of Class1's M1"
End SubPublic Sub M2()End Sub
'---------------------------------------------------------------------------------------
' Module : Class3
' Author : Anna
' Date : 2009-9-20
' Purpose : Implements Class1 and Class2
'---------------------------------------------------------------------------------------Option Explicit
Implements Class1
Implements Class2Private Sub Class1_M1()
Debug.Print "Class3's implementation of Class1's M1"
End SubPrivate Sub Class2_M2()
Debug.Print "Class3's implementation of Class2's M2"
End Sub
'---------------------------------------------------------------------------------------
' Module : Module1
' Author : Anna
' Date : 2009-9-20
' Purpose : Test Multi-Inheritance
'---------------------------------------------------------------------------------------Option ExplicitSub Test_MultiInherit()
Dim aa As Class1
Dim bb As Class2
Dim cc As Class3
Set cc = New Class3
Set bb = cc
Call bb.M2
Set bb = Nothing
Set aa = cc
Call aa.M1
Set aa = Nothing
Set cc = Nothing
End Sub
'---------------------------------------------------------------------------------------
' Module : Class3
' Author : Anna
' Date : 2009-9-20
' Purpose : Implements Class2 only
'---------------------------------------------------------------------------------------Option Explicit
Implements Class2Private Sub Class2_M2()
Debug.Print "Class3's implementation of Class2's M2"
End Sub
'---------------------------------------------------------------------------------------
' Module : Module1
' Author : Anna
' Date : 2009-9-20
' Purpose : Does VB know anything about Grandpa?
'---------------------------------------------------------------------------------------Option ExplicitSub Test_MultiInherit()
Dim aa As Class1
Dim bb As Class2
Dim cc As Class3
Set cc = New Class3
Set bb = cc
Call bb.M2' Set bb = New Class2
Set aa = bb 'Type MisMatch, 除非把上一句取消注释'
Call aa.M1
Set aa = Nothing
Set bb = Nothing
Set cc = Nothing
End Sub
上面这段代码说明,Class3能够了解自己继承自Class2,但是并不会进一步去了解Class2继承自Class1。所以你可以Set bb = cc,但是不能进一步Set aa = bb,更不能Set aa = cc。VB只能记录父类子类这样单层的继承关系。
但是Class3就不能继承Class2里的实现了。打个比方说,Class1是动物类,有个方法叫做吃(M1);Class2是哺乳动物类,Class2继承吃的方法(Class1_M1),加入自己的实现“弄死了再吃”;Class3是人,它要继承吃的方法,比较省力的办法是继承Class2的“弄死了再吃”的步骤,自己再加一个语句叫“烧熟了再吃”就可以了。可是,在VB中并不支持这样的爷孙继承。Class3如果直接继承Class2的话,它就不能继承Class2吃的方法。因为在Class2里,它继承的Class1的吃的方法是私有的(Private Sub Class1_M1)。所以,它只能直接继承Class1的M1方法,并且只好重复写上“弄死再吃”、然后加上“烧熟再吃”。
这样做虽然可以,但是假如Class1的吃的方法有一个步骤“抓住一个动物再吃”,用你的方法就无法继承了。就是说,如果我希望既继承Class1的“抓住一个动物再吃”,也希望继承Class2的“弄死了再吃”,并且希望加上自己的“烧熟了再吃”,VB6是不支持的。
Option ExplicitPublic Sub M1()
Debug.Print "吃"
End Sub
class2代码:
Option Explicit
Implements Class1
Private mobjClass1 As New Class1Public Sub M1()
Call mobjClass1.M1
Debug.Print "弄死再吃"
End SubPrivate Sub Class1_M1()
Call M1
End Sub
class3代码:
Option Explicit
Implements Class1
Private mobjClass2 As New Class2Public Sub M1()
Call mobjClass2.M1
Debug.Print "烧熟再吃"
End SubPrivate Sub Class1_M1()
Call M1
End Sub
窗口代码:
Option ExplicitPrivate Sub Form_Load()
Dim cls As New Class3
Call cls.M1
End Sub
Debug.Print "吃"
End SubClass2代码:Option Explicit
Implements Class1 ' Class2实现了Class1的默认接口
Private mobjClass1 As New Class1 ' Class2聚合了Class1的一个实例' 调用基类方法,同时添加自己的内容
Public Sub M1()
Call mobjClass1.M1
Debug.Print "弄死再吃"
End Sub' 实现基类接口
Private Sub Class1_M1()
Call M1
End SubClass3代码:Option Explicit
Implements Class1 ' Class3实现了Class1的默认接口
Implements Class2 ' Class3实现了Class2的默认接口
Private mobjClass2 As New Class2 ' Class3聚合了Class2的一个实例' 调用基类方法,同时添加自己的内容
Public Sub M1()
Call mobjClass2.M1
Debug.Print "烧熟再吃"
End Sub' 实现基类接口
Private Sub Class1_M1()
Call M1
End Sub' 实现基类接口
Private Sub Class2_M1()
Call M1
End SubForm1代码:Option ExplicitPrivate Sub Form_Load()
Debug.Print vbCrLf & "p3->Class3"
Dim p3 As Class3 ' Class3的默认接口
Set p3 = New Class3 ' Class3对象
Call p3.M1
Debug.Print vbCrLf & "p2->Class3"
Dim p2 As Class2 ' Class2接口
Set p2 = New Class3 ' Class3对象
Call p2.M1
Debug.Print vbCrLf & "p1->Class3"
Dim p1 As Class1 ' Class1接口
Set p1 = New Class3 ' Class3对象
Call p1.M1
Debug.Print vbCrLf & "p2->Class2"
Set p2 = New Class2 ' Class2对象
Call p2.M1
Debug.Print vbCrLf & "p1->Class2"
Set p1 = New Class2 ' Class1对象
Call p1.M1
Debug.Print vbCrLf & "p1->Class1"
Set p1 = New Class1 ' Class1对象
Call p1.M1
End Sub
多重接口继承好像是不支持.
指定要在包含该语句的类模块中实现的接口或类。
语法
Implements [InterfaceName | Class]
所需的 InterfaceName 或 Class 是类型库中的接口或类的名称,该类型库中的方法将用与 Visual Basic 类中相一致的方法来实现。
说明
所谓接口就是代表接口封装的成员(方法以及属性)的原型集合;也就是说,它只包含成员过程的声明部分。一个类提供一个或多个接口的所有方法以及属性的一种实现方案。类的控制者每次调用函数时,该函数所执行的代码由类来提供。每个类至少应实现一个缺省接口。在 Visual Basic 中,一个已实现的接口中任何没有显式声明的成员都是缺省接口的隐式成员。
当 Visual Basic 类实现接口时,都会提供该接口的类型库中说明的所有 Public 过程的版本。除了提供接口原型与自编过程之间的映射关系之外,Implements 语句还使这个类接收对指定接口 ID 的 COM QueryInterface 调用。
注意 Visual Basic 不能实现派生出来的类或接口。在实现接口或类时,必须包括所用到的 Public 过程。如果在实现接口或类时遗漏了成员,就会产生错误。如果正在实现的类中某个过程还没有代码,则可以产生一个适当的错误信息 (Const E_NOTIMPL = &H80004001),以便用户意识到该成员还没有实现。
Implements Class1 ' Class3实现了Class1的默认接口
Implements Class2 ' Class3实现了Class2的默认接口
Private mobjClass2 As New Class2 ' Class3聚合了Class2的一个实例
你的代码的实质:
(1)用聚合来实现多重继承
(2)用Implements来实现多态。比较典型的:
Dim p2 As Class2 ' Class2接口
Set p2 = New Class3 ' Class3对象
Call p2.M1p2.M1实际上调用了p3.M1。调用过程如下:
(1)p2实际上指向一个Class3对象
(2)由于Class3实现了Class2的M1方法,所以多态机制决定对p2.M1会被引向p3里的私有过程Class2_M1
(3)而在Class2_M1过程里你直接调用了Class3的M1方法;
(4)而在Class3的M1方法里你又通过聚合的Class2对象调用了Class2的M1方法;
(5)类似的,在Class2的M1方法中,你也通过聚合的Class1对象调用了Class1的M1方法。最后效果,就是通过调用p2.M1,你居然神奇的把从Class1到Class3可以做的事都做了。对的,所以实际上它不怎么支持继承。赞同。记得以前有次讨论,曾经有个结论说,聚合应该全面替代继承。因为继承的耦合度高,会带来一系列麻烦。好像是ahao说的,你也赞同。不知记错没?现在又觉得这个结论有点费解了。
在vb6中用聚合模拟继承是没有办法的办法。
我个人的实践是在vb6中根本不使用类模块,而是仍然使用面向过程的编程。
*****************************************************************************
欢迎使用CSDN论坛专用阅读器 : CSDN Reader(附全部源代码) http://feiyun0112.cnblogs.com/
这是C++中虚(virtual)函数的行为.如果不加virtual,而让子类的方法覆盖父类方法的话,在VB中可以不递归调用来进行模拟.
也就是说,Class3的p2.M1调用Class2的M1方法就等同于C++的虚函数,不调用的就等用于普通成员函数.
Option Explicit
Implements Class1 ' Class2实现了Class1的默认接口
Private mobjClass1 As New Class1 ' Class2聚合了Class1的一个实例' 调用基类方法,同时添加自己的内容
Public Sub M1()
Debug.Print "弄死再吃"
End Sub' 实现基类接口
Private Sub Class1_M1()
Call mobjClass1.M1
End Sub
Class3代码:
Option Explicit
Implements Class1 ' Class3实现了Class1的默认接口
Implements Class2 ' Class3实现了Class2的默认接口
Private mobjClass2 As New Class2 ' Class3聚合了Class2的一个实例' 调用基类方法,同时添加自己的内容
Public Sub M1()
Debug.Print "烧熟再吃"
End Sub' 实现基类接口
Private Sub Class1_M1()
Dim objClass1 As Class1
Set objClass1 = mobjClass2
Call objClass1.M1
End Sub' 实现基类接口
Private Sub Class2_M1()
Call mobjClass2.M1
End Sub
不好意思说错了,今天刚看的COM技术内幕
这种方式应该被称为包容而不是聚合,聚合是指直接将指针给出去的情况.
这段话说的有点问题,更正下:
实际上这并不是虚函数而是调用链的行为,即在子类的方法执行完毕后调用父类的方法,这样递归调用.如果只想让他做一件事情的话,可以不做递归调用.
Class1 爷爷
Class2 父亲 - 包含爷爷的一个实例,实现了爷爷的接口,在爷爷的接口中调用爷爷的相应方法.
Class3 本人 - 父亲的一个实例,实现了父亲和爷爷的接口,父亲的接口中调用父亲自身的方法,爷爷的接口中调用父亲实例中爷爷接口的方法.这样,Class3(本人)就可以被当作Class2(父亲)和Class1(爷爷)来使用了:)