这个问题在这里已经有了答案:
Can't seem to use Interfaces with properties in VBA and I can't work out why
(1 个回答)
5年前关闭。
我刚刚开始在 VBA 中使用类,我正在遵循“构造继承”方法概述 here .我的示例使用一个简单的类,该类包含一个值(作为变体)和一个值类型(作为字符串)。我创建了一个子类,其中值类型在构造函数中设置为字符串。这是我的代码:
接口(interface)类 (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_,要么设置为基类对象的“Base Val”,要么设置为字符串类对象的“字符串”。此外,以下属性存在“对象变量或未设置 block 变量”错误:
stringClassVal.IVal_Val
stringClassVal.IVal_ValType
我在这里有点不知所措...我认为这很简单,例如拼写错误,但我找不到。
最佳答案
那只是因为你的类(class)CStringVal
没有实现 ValType
属性(property)。好的,你实现了属性 ValType
界面IVal
但不是明确的 ValType
类本身的。
要访问接口(interface)的方法,您需要以某种方式 cast
你的对象到接口(interface)的类型。例如:
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 中的继承有点棘手,而且不是很自然。当一个类实现一个接口(interface)时,接口(interface)的方法可以通过对接口(interface)的引用来访问,而不是实现者对象,除非后者显式地重新定义了方法/属性
还要注意初始化器
val_ = Nothing
是无用的,并且在某种程度上是错误的。未初始化的 Variant
创建为 empty
变体。 Nothing
基本上用于对象,而不是基本变量(包括字符串)。正如@TimWilliams 所说,构造函数的名称是
Class_Initialize
不是 Class_Initialization
.
关于excel - VBA通过构造继承,构造函数不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42235854/