如何将所有 class 硬编码值保存在一个地方

How to save all class hardcoded values in one place

我在 VBA 中创建了一个 class,我想要一些与之关联的预设值。我是 classes 的新手,想知道在 class 对象中构建我的 VBA 代码的最佳(/好的)方法是什么,以便我可以访问这些默认值在我打字时很容易。最好回答:

值得注意的是,我对这些硬编码值的主要用途是为 class 的变量设置默认值(通过在 initialize 事件中循环),但我可能还想在代码的其他部分访问它们

我尝试过的:

声明一个 Enum 来保存我的硬编码值

'Declarations
Private Enum startingVals
    Top = 10
    Column_Count = 4
    Left = 15
    ...
End Enum
Private topVal As Long 'variables which I assign default values to
Private colCnt As Long
Private leftVal As Long

Private Sub Class_Initialize()
topVal = startingVals.Top
colCnt = startingVals.Column_Count
'etc.
End Sub

这有两个限制;

理想情况下我可以做到这一点

Private Sub Class_Initialize()
With startingVals 'or Dim v As startingVals, With v
    topVal = .Top
    colCnt = .Column_Count
    'etc.
End With
End Sub

但是我不能


另一种方法是使用函数来保存值,这样您就可以将不同的类型声明为 long。

'Declarations
Private Enum startingVals
    Top = 1
    Column_Count = 2
    Left = 3
    ...
End Enum
Private topVal As Long 'variables which I assign default values to
Private colCnt As Long
Private leftVal As Long

Private Sub Class_Initialize()
topVal = getval(Top)
colCnt = getval(Column_Count)
'etc.
End Sub

然后为了访问硬编码数据,你有一个函数接受枚举输入(允许智能感知)

Private Function getval(dataType As startVals) As String
Const savedData As String = "1,2,1.17171717,hey,me,you" 'save the return values for the index specified by dataType
getval = Split(savedData, ",")(dataType) 'use datatype as a direct index of the array
End Function

或另一种保存值的方法

Private Function getval(dataType As startVals) As String
Const colV As Long = 10 'index 1
Const topV As String = "This is the top" 'index 2
'...
If dataType = ColumnCount Then getval = colV 'use dataType to check what to return
If dataType = Top Then getval = colV 'could use a select case too
'etc
End Function

TL;DR

在 class 对象中保存硬编码值的最佳方法是什么,其中最佳定义为

我不能声明对这个解决方案的所有权,但是当我 运行 在 Code Review 上重新使用它时,它对我来说已经足够天才了,可以将它合并到我的很多代码中,因为.

正如在其他一些面向对象语言中所使用的那样,使用 this 构造访问 class-内部实例变量是非常熟悉的。使用此处的示例将概念扩展为 VBA。

我创建了一个名为 CustomClass 的 class 模块,并在其中创建了一个 私有自定义类型,仅供在 class 中使用].

Option Explicit

Private Type CustomType
    Top As Long
    Name As String
    Temperature As Double
    anotherCustomObject As CustomClass
End Type
Private this As CustomType

通过这种方式,您可以创建任意数量的任意类型组合(包括对象)的内部变量。现在访问和初始化这些值中的每一个都像使用 this 结构化变量一样简单。 Class_Initialize 子说明如何:

Private Sub Class_Initialize()
    this.Top = 150
    this.Name = "Wayne"
    this.Temperature = 98.6
    Set this.anotherCustomObject = New CustomClass
End Sub

根据自己的喜好设置和初始化所有值。

此外,您可以根据需要为每个访问器创建 属性 访问器。其中一些可以是只读的:

'--- Read Only Properties
Public Property Get Name() As String
    Name = this.Name
End Property

Public Property Get Temperature() As Double
    Temperature = this.Temperature
End Property

Public Property Get ContainedObject() As CustomClass
    Set ContainedObject = this.anotherCustomObject
End Property

你可以创建一些 Read/Write:

'--- Read/Write Properties
Public Property Let Top(ByVal newValue As Long)
    this.Top = newValue
End Property

Public Property Get Top() As Long
    Top = this.Top
End Property

此外,您仍然可以使用 Me 关键字在 class 中轻松使用属性:

'--- Internal Private Methods
Private Sub TestThisClass()
    Debug.Print "current temperature is " & Me.Temperature
    Debug.Print "the Top value is " & Me.Top
End Sub

当然,当您在不同的模块中声明 CustomClass 的对象时,这一切都有效。

希望这有助于稍微规范您的代码。

(为方便起见,这里是整个class:)

Option Explicit

Private Type CustomType
    Top As Long
    Name As String
    Temperature As Double
    anotherCustomObject As CustomClass
End Type
Private this As CustomType

Private Sub Class_Initialize()
    this.Top = 150
    this.Name = "Wayne"
    this.Temperature = 98.6
    Set this.anotherCustomObject = New CustomClass
End Sub

'--- Read Only Properties
Public Property Get Name() As String
    Name = this.Name
End Property

Public Property Get Temperature() As Double
    Temperature = this.Temperature
End Property

Public Property Get ContainedObject() As CustomClass
    Set ContainedObject = this.anotherCustomObject
End Property

'--- Read/Write Properties
Public Property Let Top(ByVal newValue As Long)
    this.Top = newValue
End Property

Public Property Get Top() As Long
    Top = this.Top
End Property

'--- Internal Private Methods
Private Sub TestThisClass()
    Debug.Print "current temperature is " & Me.Temperature
    Debug.Print "the Top value is " & Me.Top
End Sub

您可以使用常量在一个地方定义默认值。

然后您可以使用 Ctrl + Space + 默认...轻松访问它们...

Const Default_Top = 10
Const Default_Text = "abcd"

Private m_topVal As Long
Private m_text As String

Private Sub Class_Initialize()
  m_topVal = Default_Top
  m_text = Default_Text
End Sub

Public Property Get TopVal() As Long
  TopVal = m_topVal
End Property

...to prevent my class from becoming too cluttered

我会将 class 与其初始化过程分开,添加另一个 class 让我们称之为 Initializer。 Initializer 将知道如何初始化我的对象,将包含默认值并使用此默认值填充我的对象。但是在初始化程序中,您将不得不编写作业,没有神奇的智能感知,而只是简单地从列表中编写 m_ 和 select 。 HTH

Class Foo

Option Explicit

'variables which I assign default values to
Private m_topVal As Long
Private m_colCnt As Long
'Private m_leftVal As Long

Private Sub Class_Initialize()
    Dim initializer As FooInitializer
    Set initializer = New FooInitializer
    initializer.Initialize Me
End Sub

Public Property Get TopVal() As Long
    TopVal = m_topVal
End Property

Public Property Let TopVal(ByVal vNewValue As Long)
    m_topVal = vNewValue
End Property

Public Property Get ColCnt() As Long
    ColCnt = m_colCnt
End Property

Public Property Let ColCnt(ByVal vNewValue As Long)
    m_colCnt = vNewValue
End Property

' Add Get/Let(Set) for other member variables as well

Class FooInitializer

Option Explicit

' Default startingVals values
Private m_topValDefault As Integer
Private m_columnCountDefault As Integer
'etc.

Public Sub Initialize(ByRef fooInstance As Foo)
    fooInstance.TopVal = m_topValDefault
    fooInstance.ColCnt = m_columnCountDefault
    'etc.
End Sub

Private Sub Class_Initialize()
    m_topValDefault = 10
    m_columnCountDefault = 4
    'etc.
End Sub

Standard module

Option Explicit

Sub test()
    Dim f As Foo
    Set f = New Foo
    ' f is now initizlized via initializer with default values
    Debug.Print f.TopVal
    Debug.Print f.ColCnt
End Sub