VBA继承通过构建,构造器不工作? [英] VBA inheritance via construction, constructor not working?

查看:143
本文介绍了VBA继承通过构建,构造器不工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始在VBA中使用课程,并且我遵循了概述的继承继承方法。这里。我的示例使用一个包含值(作为变体)和值类型(作为字符串)的简单类。我创建了一个子类,其中值类型在构造函数中设置为字符串。这是我的代码:



接口类(IVal)

  IVal界面类(从https://www.theartofquantfinance.com/inheritance-by-construction-in-vba/)
选项显式

'--------- --------------------------
'ValType
'的访问方法---------- -------------------------
公共属性Get ValType()As String
结束属性
公共属性Let ValType(ByVal RHS As String)
结束属性
'-------------------------------- ---
'Val
'的访问方法--------------------------------- -
公共属性Get Val()As Variant
结束属性
公共属性让Val(ByVal RHS As Variant)
结束属性

'添加其他方法在这里作为公共子
'ie
'Public Sub HonkHorn()
'End Sub

基类(CBaseVal )

 'CBaseVal基类 - 实现IVal界面(从https://www.theartofquantfinance.com/inheritance-by-construction -in-vba /)
选项显式
实现IVal

'----------------------- -------
'私人字段
'------------------------------
私人valType_作为字符串
私人val_作为变式

'-------------------------- ----
'构造函数和析构函数
'------------------------------
Private Sub Class_Initialization()
valType_ =Base Val
val_ = Nothing
End Sub
'---------------- --------------
'类属性和方法 - public,对所有模块都可见
'这些将在接口类
'中声明 - ----------------------------
公共属性获取ValType()As String
ValType = valType_
结束财产
Pu blic属性让ValType(ByVal RHS As String)
valType_ = RHS
结束属性

公共属性Get Val()As Variant
Val = val_
结束属性
公共属性让Val(ByVal RHS As Variant)
val_ = RHS
结束属性

'添加其他类方法
'eg
'Public Sub HonkHorn()
'MsgBox提示符:=Beep !!!
'End Sub

'------------------------------
'接口属性和方法实现 - 私有,只对该模块可见
'使用Me代表接口属性和方法(基础)
'----------- -------------------
私有属性让IVal_Val(ByVal RHS as Variant)
Me.Val = RHS
结束属性

私有属性Get IVal_Val()As Variant
IVal_Val = Me.Val
结束属性

私有属性让IVal_ValType(ByVal RHS As String)
Me.ValType = RHS
结束属性

私有属性Get IVal_ValType()As String
IVal_ValType = Me.ValType
结束属性

'End Property
'在这里添加其他IF方法
'ie
'Private Sub ICar_HonkHorn()
'Call Me.HonkHorn
'End Sub

儿童类(CStringVal)

 'CStringVal类 - 实现IVal界面,并酌情委派给CVal(从https ://www.theartofquantfinance.com/inheritance-by-construction-in-vba/)
选项显式
实现IVal

'--------- ---------------------
'私人字段
'----------------- -------------
Private baseVal_由于IVal'包含IVal类的一个实例(为什么不是作为CBaseVal?)

' ------------------------------
'构造函数和析构函数
'------- -----------------------
Private Sub Class_Initialization()
Set baseVal_ = New CBaseVal'initialize private field of typeval class
baseVal_.ValType =string
baseVal_.Val = Nothing
End Sub
'------------------ ------------
'类属性和方法(这里是在那里你超过基类实现)
'这些将在基类中声明,下面的接口实现将委托给这里或基类
'--------- ---------------------
'eg
'Public Sub HonkHorn()
'MsgBox提示符:=Beep !!!
'End Sub


'------------------------------
'接口属性和方法实现 - 在基类中声明,并且:
'=>大多数代表基类
'=>有些可能覆盖基类并在这里委托
'------------------------------
私有属性让我们IVal_Val(ByVal RHS As Variant)
baseVal_.Val = RHS'代表基类
结束属性

私有属性Get IVal_Val()As Variant
IVal_Val = baseVal_ val
结束属性

私有属性让IVal_ValType(ByVal RHS As String)
baseVal_.Val = RHS'代表基类
结束属性

私有属性Get IVal_ValType()As String
IVal_ValType = baseVal_.ValType'代表基类
结束属性

'添加其他接口方法

'Private Sub ICar_HonkHorn()
'调用Me.HonkHorn'覆盖基类实现,代表上面的类方法
'End Sub
pre>

这里是我用来测试的代码:

  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 

如果我注释掉该行,则代码运行但使用手表,似乎valType_未被设置,或者作为Bas e Val作为基类对象,或者作为字符串类对象的string。此外,以下属性还有Object variable or With block variable not set错误:

  stringClassVal.IVal_Val 
stringClassVal.IVal_ValType

我有点失落在这里...我认为这是简单的像一个拼写错误但是找不到它。

解决方案

这只是因为你的课程 CStringVal 不实现 ValType 属性。好的,你实现了界面 IVal 的属性 ValType ,而不是显式的 ValType 该类本身。



要访问界面的方法,您需要以某种方式向 cast 您的对象到界面的类型。例如:

  Dim itf As IVal 
Dim stringClassVal As New CStringVal
Set itf = stringClassVal'< ; - 将对象转换为界面的类型
',现在:
c = itf.ValType

,或者您可以使用定义的名称:

  c = stringClassVal.IVal_ValType 

但请注意,您尚未初始化变量的字段(使用getter之前的字母)。



是的,VBA / VB6中的继承是有点棘手而不是很自然的。当一个类实现一个接口时,接口的方法可以通过对接口的引用来访问,而不是对实现者对象的访问,除非后者明确地重新定义方法/ property



还要注意,初始化程序 val_ = Nothing 是无用的,不知何故。未初始化的变式创建为变体。 没有什么基本上用于对象,而不是用于基本变量(包括字符串)。



另外,作为@TimWilliams说构造函数的名称是 Class_Initialize not Class_Initialization


I am just getting started using classes in VBA and I'm following the "Inheritance by construction" method outlined here. My example uses a simple class that contains a value (as a variant) and a value type (as a string). I created a subclass in which value type is set to string in the constructor. Here is my code:

Interface Class (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

Base Class (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

Child Class (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

And here is the code I'm using to test it:

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

The first problem is a compile error that "Method or data member not found" for the line

c = stringClassVal.ValType

If I comment out that line, the code runs but using Watches it appears that valType_ is not being set, either as "Base Val" for the base class object or as "string" for the string class object. Additionally, there are "Object variable or With block variable not set" errors for the following properties:

stringClassVal.IVal_Val
stringClassVal.IVal_ValType

I'm kind of at a loss here... I assume it's something simple like a misspelling but I can't find it.

解决方案

That's simply because your class CStringValdoes not implement the ValType property. Ok, your implemented the property ValType of the interface IVal but not the explicit ValType of the class itself.

To access the interface's method, you need somehow to cast your object to the interface's type. For example:

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

or you can use the defined name:

c = stringClassVal.IVal_ValType

But notice you did not initialize the fields of the variable yet (use the letters before the getters).

Yes, inheritance in VBA/VB6 is somehow tricky and not very natural. When a class implements an interface, the interface's methods are accessible through a reference to the interface, not to the implementor object, unless the latter explicitly redefines the method/property

Also notice that the initializer val_ = Nothing is useless and somehow wrong. An uninitialized Variant is created as an empty variant. Nothing basically is used for objects, not for basic variables (including strings).

Also as @TimWilliams said the constructor's name is Class_Initialize not Class_Initialization.

这篇关于VBA继承通过构建,构造器不工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆