我刚刚开始在VBA中使用类,而且我正在遵循"继承施工"方法概述here。我的示例使用一个包含值(作为变量)和值类型(作为字符串)的简单类。我创建了一个子类,其中值类型在构造函数中设置为string。这是我的代码:
接口类(IVal)
'IVal interface class (from https://www.theartofquantfinance.com/inheritance-by-construction-in-vba/)
Option Explicit
'-----------------------------------
'Accessor methods for ValType
'-----------------------------------
Public Property Get ValType() As String
End Property
Public Property Let ValType(ByVal RHS As String)
End Property
'-----------------------------------
'Accessor methods for Val
'-----------------------------------
Public Property Get Val() As Variant
End Property
Public Property Let Val(ByVal RHS As Variant)
End Property
'Add other methods here as "Public Sub"
'i.e.
'Public Sub HonkHorn()
'End Sub
基类(CBaseVal)
'CBaseVal base class - implements IVal interface (from https://www.theartofquantfinance.com/inheritance-by-construction-in-vba/)
Option Explicit
Implements IVal
'------------------------------
'Private Fields
'------------------------------
Private valType_ As String
Private val_ As Variant
'------------------------------
'Constructors and destructors
'------------------------------
Private Sub Class_Initialization()
valType_ = "Base Val"
val_ = Nothing
End Sub
'------------------------------
'Class Properties And methods - public, visible to all modules
'These would be declared in the interface class
'------------------------------
Public Property Get ValType() As String
ValType = valType_
End Property
Public Property Let ValType(ByVal RHS As String)
valType_ = RHS
End Property
Public Property Get Val() As Variant
Val = val_
End Property
Public Property Let Val(ByVal RHS As Variant)
val_ = RHS
End Property
'Add additional class methods here
'e.g.
'Public Sub HonkHorn()
' MsgBox prompt:="Beep!!!"
'End Sub
'------------------------------
'Interface property and method implementation - private, only visible to this module
'Delegate interface properties and methods to this (base) class using "Me"
'------------------------------
Private Property Let IVal_Val(ByVal RHS As Variant)
Me.Val = RHS
End Property
Private Property Get IVal_Val() As Variant
IVal_Val = Me.Val
End Property
Private Property Let IVal_ValType(ByVal RHS As String)
Me.ValType = RHS
End Property
Private Property Get IVal_ValType() As String
IVal_ValType = Me.ValType
End Property
'End Property
'Add additional IF methods here
'i.e.
'Private Sub ICar_HonkHorn()
' Call Me.HonkHorn
'End Sub
子类(CStringVal)
'CStringVal class - implements IVal interface and delegates to CVal as appropriate (from https://www.theartofquantfinance.com/inheritance-by-construction-in-vba/)
Option Explicit
Implements IVal
'------------------------------
'Private Fields
'------------------------------
Private baseVal_ As IVal 'contains an instance of the IVal class (why isn't this "As CBaseVal"?)
'------------------------------
'Constructors and destructors
'------------------------------
Private Sub Class_Initialization()
Set baseVal_ = New CBaseVal 'initialize private field of type "val class"
baseVal_.ValType = "string"
baseVal_.Val = Nothing
End Sub
'------------------------------
'Class Properties And methods (here's where you over-ride the base class implementation)
'These would be declared in the base class and the interface implementation below will delegate to either here or base class
'------------------------------
'e.g.
'Public Sub HonkHorn()
' MsgBox prompt:="Beep!!!"
'End Sub
'------------------------------
'Interface property and method implementation - declared in base class and either:
'=> most delegate to base class
'=> some may override base class and delegate here
'------------------------------
Private Property Let IVal_Val(ByVal RHS As Variant)
baseVal_.Val = RHS 'Delegate to base class
End Property
Private Property Get IVal_Val() As Variant
IVal_Val = baseVal_.Val
End Property
Private Property Let IVal_ValType(ByVal RHS As String)
baseVal_.Val = RHS 'Delegate to base class
End Property
Private Property Get IVal_ValType() As String
IVal_ValType = baseVal_.ValType 'Delegate to base class
End Property
'Add additional interface methods here
'i.e.
'Private Sub ICar_HonkHorn()
' Call Me.HonkHorn 'Overrides base class implementation, delegates to class method above
'End Sub
以下是我用来测试它的代码:
Public Sub testStringValClass()
Dim interfaceClassVal As IVal
Dim baseClassVal As CBaseVal
Dim stringClassVal As CStringVal
Set interfaceClassVal = New IVal
Set baseClassVal = New CBaseVal
Set stringClassVal = New CStringVal
a = interfaceClassVal.ValType
b = baseClassVal.ValType
c = stringClassVal.ValType
End Sub
第一个问题是编译错误,"找不到方法或数据成员"为行
c = stringClassVal.ValType
如果我注释掉那一行,代码会运行,但是使用Watches,似乎没有设置valType_,或者#34; Base Val"对于基类对象或作为"字符串"用于字符串类对象。此外,还有"对象变量或With块变量未设置"以下属性的错误:
stringClassVal.IVal_Val
stringClassVal.IVal_ValType
我在这里有点不知所措......我认为它像拼写错误一样简单,但我无法找到它。
答案 0 :(得分:1)
这仅仅是因为您的班级CStringVal
没有实现ValType
属性。好的,您实现了接口ValType
的属性IVal
,但未实现类本身的显式ValType
。
要访问界面的方法,您需要以某种方式将cast
您的对象添加到界面的类型中。例如:
Dim itf As IVal
Dim stringClassVal As New CStringVal
Set itf = stringClassVal '<-- casts the object to the interface's type
' and now:
c = itf.ValType
或者您可以使用定义的名称:
c = stringClassVal.IVal_ValType
但请注意,您尚未初始化变量的字段(使用getter之前的字母)。
是的,VBA / VB6中的继承在某种程度上是棘手的,并不是很自然。当类实现接口时,接口的方法可以通过对接口的引用而不是实现者对象来访问,除非后者显式地重新定义方法/属性
另请注意,初始化程序val_ = Nothing
没用,而且有些错误。未初始化的Variant
被创建为empty
变体。 Nothing
基本上用于对象,而不是基本变量(包括字符串)。
同样@TimWilliams说构造函数的名称是Class_Initialize
而不是Class_Initialization
。