如何将所有 class 硬编码值保存在一个地方
How to save all class hardcoded values in one place
我在 VBA 中创建了一个 class,我想要一些与之关联的预设值。我是 classes 的新手,想知道在 class 对象中构建我的 VBA 代码的最佳(/好的)方法是什么,以便我可以访问这些默认值在我打字时很容易。最好回答:
- 除了我认为对值的实际硬编码所需的行之外,需要相对较少的额外代码行
- 即。每个硬编码值的附加
Sub
之类的东西并不理想
- 这是为了防止我的 class 变得太乱
- 请允许我以某种方式使用智能感知来访问这些硬编码值
值得注意的是,我对这些硬编码值的主要用途是为 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
这有两个限制;
- 枚举只能存储
Long
s
- 通过使用
Const
的负载来解决这个问题,但是你必须记住每个常量的名称,而且它在代码中看起来很混乱
- 虽然我获得了
.Top
和 .Column_Count
的 Intellisense,但我仍然必须完整地输入 startingVals
- 虽然这比必须记住所有硬编码常量名称要好得多
理想情况下我可以做到这一点
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
- 但无论哪种方式,除非我们键入函数名称,否则我们仍然无法访问常量。
- 此外,这种方法要求我更新 class 声明部分的枚举声明和函数本身内的 const 声明,使代码更难维护。
TL;DR
在 class 对象中保存硬编码值的最佳方法是什么,其中最佳定义为
- 使用 VBA 智能感知(自动填充),因此我可以在键入时快速 select 我想要的值
- 在我的 class 模块中整洁、独立且简洁,以避免混乱
- 可以最好地保存任何类型(数据类型)的硬编码值(尽管我只在我目前正在处理的项目中使用
Long
)
- 无需每次都输入初始化部分即可访问(例如
function
或enum
名称)
- 当然,
With
块或等效函数就可以了,因为这只需要指定 enum/data 集合名称的一个实例
我不能声明对这个解决方案的所有权,但是当我 运行 在 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
我在 VBA 中创建了一个 class,我想要一些与之关联的预设值。我是 classes 的新手,想知道在 class 对象中构建我的 VBA 代码的最佳(/好的)方法是什么,以便我可以访问这些默认值在我打字时很容易。最好回答:
- 除了我认为对值的实际硬编码所需的行之外,需要相对较少的额外代码行
- 即。每个硬编码值的附加
Sub
之类的东西并不理想 - 这是为了防止我的 class 变得太乱
- 即。每个硬编码值的附加
- 请允许我以某种方式使用智能感知来访问这些硬编码值
值得注意的是,我对这些硬编码值的主要用途是为 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
这有两个限制;
- 枚举只能存储
Long
s- 通过使用
Const
的负载来解决这个问题,但是你必须记住每个常量的名称,而且它在代码中看起来很混乱
- 通过使用
- 虽然我获得了
.Top
和.Column_Count
的 Intellisense,但我仍然必须完整地输入 startingVals- 虽然这比必须记住所有硬编码常量名称要好得多
理想情况下我可以做到这一点
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
- 但无论哪种方式,除非我们键入函数名称,否则我们仍然无法访问常量。
- 此外,这种方法要求我更新 class 声明部分的枚举声明和函数本身内的 const 声明,使代码更难维护。
TL;DR
在 class 对象中保存硬编码值的最佳方法是什么,其中最佳定义为
- 使用 VBA 智能感知(自动填充),因此我可以在键入时快速 select 我想要的值
- 在我的 class 模块中整洁、独立且简洁,以避免混乱
- 可以最好地保存任何类型(数据类型)的硬编码值(尽管我只在我目前正在处理的项目中使用
Long
) - 无需每次都输入初始化部分即可访问(例如
function
或enum
名称)- 当然,
With
块或等效函数就可以了,因为这只需要指定 enum/data 集合名称的一个实例
- 当然,
我不能声明对这个解决方案的所有权,但是当我 运行 在 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