excel - VBA通过构造继承,构造函数不起作用?

标签 excel vba class inheritance constructor

这个问题在这里已经有了答案:





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/

相关文章:

excel - 创建数据透视表时过程调用或参数无效

c# - 方法已执行但未生效

python - XLWINGS:如何选择没有标题的整列?

vba - 数据进入错误的工作簿

r - 如何在excel中将数字转换为日期时间格式(我在R中实现了等效的解决方案)

excel - CSV 文件必须保存两次

上个月名称的VBA代码

excel - VBA Exp() 溢出

javascript - ExpressJS 子类在回调中缺少继承的属性和属性

python - 如何将带有 2 个参数的类字典复制到 2 个列表中