VBA:有抽象类之类的东西吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21220317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
VBA: is there something like Abstract Class?
提问by mins
I'm using an interface to ensure some similar classes implements some mandatory methods (subs/functions).
我正在使用一个接口来确保一些类似的类实现了一些强制方法(子/函数)。
Example:
例子:
- interface I1 declares M1 and M2 methods
- C1 and C2 implement I1, and have their own versions for M1 and M2.
- 接口 I1 声明了 M1 和 M2 方法
- C1 和 C2 实现了 I1,并且有自己的 M1 和 M2 版本。
C1 and C2 also need methods that are exactly the same, for example methods SM1 and SM2.
C1 和 C2 也需要完全相同的方法,例如方法 SM1 和 SM2。
To avoid repeating SM1 and SM2 I'd like to define an abstract class AC:
为了避免重复 SM1 和 SM2,我想定义一个抽象类 AC:
- implementing I1
- defining SM1 and SM2.
- 实施 I1
- 定义 SM1 和 SM2。
which would be extended by C1 and C2
由 C1 和 C2 扩展
This solution is indeed possible in Java, but I don't find any documentation for doing the same in VBA. (VB.Net seems to allow abstract classes using keyword MustInherit.)
这个解决方案在 Java 中确实是可能的,但我没有找到任何在 VBA 中执行相同操作的文档。(VB.Net 似乎允许使用关键字 MustInherit 的抽象类。)
Any confirmation it is possible or not in VBA?
任何确认在 VBA 中是否可能?
回答by GSerg
There is no inheritance in VBA.
VBA 中没有继承。
You can define an interface and you can implement it in a class by using the Implements
keyword. But if you want shared functionality pre-implemented by a base class, you have to use the copy-paste approach.
您可以定义一个接口,并且可以使用Implements
关键字在类中实现它。但是,如果您想要由基类预先实现的共享功能,则必须使用复制粘贴方法。
Related reading:
How to use the Implements in Excel VBA
How to use comparison methods between class object modules in VBA in a similar manner as VB.NET?
相关阅读:
如何在Excel VBA中使用Implements
如何以与VB.NET类似的方式在VBA中使用类对象模块之间的比较方法?
回答by dee
You could implement semi-decorator :-) pattern in VBA. Lets say we have a base class and two child classes. If you use Implements keyword in child classes you will garatee that child classes has the same interface as the base class and at the same time declare a private instance of base class in each child class and redirect calls from children to base class.
您可以在 VBA 中实现半装饰器 :-) 模式。假设我们有一个基类和两个子类。如果您在子类中使用Implements 关键字,您将保证子类具有与基类相同的接口,同时在每个子类中声明基类的私有实例并将子类的调用重定向到基类。
Note: base class here is normal class, you can still create instances of it (so it is not real abstract class).
注意:这里的基类是普通类,你仍然可以创建它的实例(所以它不是真正的抽象类)。
Example:
例子:
' Standard module
Sub main()
Dim a As New ChildA
Dim b As New ChildB
a.State = 2
b.State = 5
Debug.Print TypeOf a Is Base
Debug.Print TypeOf b Is Base
TestPolymorphic a
TestPolymorphic b
End Sub
Private Sub TestPolymorphic(ByRef obj As Base)
obj.Polymorphic
End Sub
' -----------------------------------------------
' Base class module
Private m_state As Byte
Public Event StateChanged(oldState As Byte, newState As Byte)
Public Property Get State() As Byte
State = m_state
End Property
Public Property Let State(ByVal newState As Byte)
Dim oldState As Byte
oldState = m_state
m_state = newState
RaiseEvent StateChanged(oldState, newState)
End Property
Sub Polymorphic()
Err.Raise 123, , "Implement in child class"
End Sub
Private Sub Class_Initialize()
m_state = 1
End Sub
' -----------------------------------------------
' ChildA class module
Implements Base
Private WithEvents m_base As Base
Private Sub Class_Initialize()
Set m_base = New Base
End Sub
Public Property Get State() As Byte
State = Base_State
End Property
Public Property Let State(ByVal newState As Byte)
Base_State = newState
End Property
Public Sub Polymorphic()
Base_Polymorphic
End Sub
Private Property Get Base_State() As Byte
Base_State = m_base.State
End Property
Private Property Let Base_State(ByVal newState As Byte)
m_base.State = newState
End Property
Private Sub Base_Polymorphic()
Debug.Print "In Child A ..."
End Sub
Private Sub m_base_StateChanged(oldState As Byte, newState As Byte)
Debug.Print "State of 'Child A' instance has changed from " & oldState & " to " & newState
End Sub
Output:
' State of 'Child A' instance has changed from 1 to 2
' State of 'Child B' instance has changed from 1 to 5
' True
' True
' In Child A ...
' In Child B ...
回答by Lucius Matos
My solution for abstract class in vba: View
我在 vba 中的抽象类的解决方案: 查看
'-------------------------
' Standard module
Sub Main()
Dim objC1 As C1
Dim objC2 As C2
Dim objCollection As New Collection
Set objC1 = New C1
Set objC2 = New C2
With objC1
.getInterface.M1 "Hello C1!"
temp1 = .getInterface.M2(objCollection)
.getSuperClass.SM1 "Hi C1!!!"
temp3 = .getSuperClass.SM2(objCollection)
End With
Debug.Print vbCrLf
With objC2
.getInterface.M1 "Hello C2!"
temp1 = .getInterface.M2(objCollection)
.getSuperClass.SM1 "Hi C2!!!"
temp3 = .getSuperClass.SM2(objCollection)
End With
End Sub
' -----------------------------------------------
' IAbstracat class module
Sub SM1(strString As String): End Sub
Function SM2(varItem As Variant) As String: End Function
' -----------------------------------------------
' Abstracat class module
Implements IAbstract
'Each class must implement these methods, in a particular way
Sub M1(strString As String): End Sub
Function M2(varItem As Variant) As String: End Function
'The sub classes will extend SM1 and SM2
Private Sub IAbstract_SM1(strString As String)
Debug.Print "Sub IAbstract_SM1: " & strString
End Sub
'The sub classes will extend SM1 and SM2
Private Function IAbstract_SM2(varItem As Variant) As String
Dim strMyString As String
strMyString = "Function IAbstract_SM2 => ObjPtr(varItem): " & ObjPtr(varItem)
Debug.Print strMyString
IAbstract_SM2 = strMyString
End Function
' -----------------------------------------------
' C1 class module
Implements Abstract
Private Type TC1
objConcretSuperClass As Abstract
objInterfaceSuperClass As IAbstract
objInterfaceSubClass As Abstract
End Type
Private this As TC1
'if you do not need to initialize anything, then this is it:
Private Sub Class_Initialize()
With this
'creating an instance of class' Abstract'
Set .objConcretSuperClass = New Abstract
'Referencing the' Abstract 'interface, where are the extended methods
Set .objInterfaceSuperClass = .objConcretSuperClass
'Creating a refence for the C1 interface, which is the class' Abstract'
'Here we have the particular implementations of M1 and M2
Set .objInterfaceSubClass = Me
End With
End Sub
'With this we can do:
' set objC1 = New C1
' objC1.getInterface.Abstract_M1
' objC1.getInterface.Abstract_M2
Property Get getInterface() As Abstract
Set getInterface = this.objInterfaceSubClass
End Property
'With this we can call the methods defined in' Abstract ': SM1 and SM2
' set objC1 = New C1
' objC1.getSuperClass.SM1 "hello!"
' temp = objC1.getSuperClass.SM2 (New Collection)
Property Get getSuperClass() As IAbstract
Set getSuperClass = this.objInterfaceSuperClass
End Property
'Here we have the particular implementations of M1 and M2
Private Sub Abstract_M1(strString As String)
Debug.Print "Class C1 => Sub Abstract_M1: " & strString
End Sub
Private Function Abstract_M2(varItem As Variant) As String
Debug.Print "Class C1 => Function Abstract_M2: " & ObjPtr(varItem)
End Function
' -----------------------------------------------
' C2 class module
Implements Abstract
Private Type TC2
objConcretSuperClass As Abstract
objInterfaceSuperClass As IAbstract
objInterfaceSubClass As Abstract
End Type
Private this As TC2
'if you do not need to initialize anything, then this is it:
Private Sub Class_Initialize()
With this
'creating an instance of class' Abstract'
Set .objConcretSuperClass = New Abstract
'Referencing the' Abstract 'interface, where are the extended methods
Set .objInterfaceSuperClass = .objConcretSuperClass
'Creating a refence for the C1 interface, which is the class' Abstract'
'Here we have the particular implementations of M1 and M2
Set .objInterfaceSubClass = Me
End With
End Sub
'With this we can do:
' set objC2 = New C2
' objC2.getInterface.Abstract_M1
' objC2.getInterface.Abstract_M2
Property Get getInterface() As Abstract
Set getInterface = this.objInterfaceSubClass
End Property
'With this we can call the methods defined in' Abstract ': SM1 and SM2
' set objC1 = New C1
' objC1.getSuperClass.SM1 "hello!"
' temp = objC1.getSuperClass.SM2 (New Collection)
Property Get getSuperClass() As IAbstract
Set getSuperClass = this.objInterfaceSuperClass
End Property
'Here we have the particular implementations of M1 and M2
Private Sub Abstract_M1(strString As String)
Debug.Print "Class C2 => Sub Abstract_M1: " & strString
End Sub
Private Function Abstract_M2(varItem As Variant) As String
Debug.Print "Class C2 => Function Abstract_M2: " & ObjPtr(varItem)
End Function
Immediate Check Window (CTRL + G):
立即检查窗口 (CTRL + G):
Class C1 => Sub Abstract_M1: Hello C1!
Class C1 => Function Abstract_M2: 550324728
Sub IAbstract_SM1: Hi C1!!!
Function IAbstract_SM2 => ObjPtr(varItem): 550324728
Class C2 => Sub Abstract_M1: Hello C2!
Class C2 => Function Abstract_M2: 550324728
Sub IAbstract_SM1: Hi C2!!!
Function IAbstract_SM2 => ObjPtr(varItem): 550324728