Vba “类”;让我们;陷入无限循环
请原谅代码中的任何愚蠢错误,因为这是我第一次尝试使用类,而且我在网上找不到任何教程可以用非常非常简单的术语来描述像我这样的傻瓜。我尽了最大的努力去遵循微软的指南,但我并不真正理解我在做什么,这使得我很难理解我应该改变什么 我试图创建一个类,它存储三段数据,两个整数和一个字符串。我把它放在一个名为Vba “类”;让我们;陷入无限循环,vba,excel,Vba,Excel,请原谅代码中的任何愚蠢错误,因为这是我第一次尝试使用类,而且我在网上找不到任何教程可以用非常非常简单的术语来描述像我这样的傻瓜。我尽了最大的努力去遵循微软的指南,但我并不真正理解我在做什么,这使得我很难理解我应该改变什么 我试图创建一个类,它存储三段数据,两个整数和一个字符串。我把它放在一个名为tdata的类模块中: Sub tdata() Dim tnumber As Integer, tacct As Integer Dim ttype As String Public Property
tdata
的类模块中:
Sub tdata()
Dim tnumber As Integer, tacct As Integer
Dim ttype As String
Public Property Get t_acct() As Integer 'don't forget the account number!
t_acct = tacct
End Property
Public Property Let t_acct(ByVal newval As Integer)
t_acct = newval
End Property
Public Property Get t_numb() As Integer 'T1, T2, or T3 as applicable
t_numb = tnumb
End Property
Public Property Let t_numb(ByVal newval As Integer)
t_numb = newval
End Property
Public Property Get t_type() As String 'PF or MW
t_type = ttype
End Property
Public Property Let t_type(ByVal newstr As String)
t_type = newstr
End Property
End Sub
然后我在函数中使用
Set t_info = New tdata
t_info.t_acct = wb2.Sheets(1).Cells(d, 1) 'd is just a row counter in a for loop
t_info.t_numb = Right(wb2.Sheets(1).Cells(d, 4), 1)
t_info.t_type = wb2.Sheets(1).Cells(d, 6)
references(CStr(wb2.Sheets(1).Cells(d, 5))).Add t_info
(当然,这不是全部代码,只是调用它的部分)
我有了选项Explicit
和所有有趣的东西,所有的东西都编译得很好,但是当它到达函数片段的第二行时,它试图使t\u info.t\u acct
等于某个值,它就指向Let
函数,并永远停留在那里。具体来说,它会在
Public Property Let t_acct(ByVal newval As Integer)
t_acct = newval
永远。为什么会这样?我如何使它设置(呃,让)等于我想要的东西 您的问题是:
这应该是分配封装字段(tacct
),而不是它本身
我将给你们我的秘方:每当我创建一个新的类模块时,我都从一个私有类型开始:
Option Explicit
Private Type TData 'assuming class module is named 'Data'
Number As Integer
Account As Integer
AccountType As String
End Type
然后,我声明了一个该类型的私有字段,名为this:
Private this As TData
有些人可能会争辩说,这个
让一切都变得如此混乱,因为这个
(私有字段)不是Me
(对象实例),在其他语言中,这个
指的是对象实例等等——如果它让你感到困惑,那就给它取你喜欢的名字吧(背衬
和封装
也很好!)
现在,所有属性都变得非常清晰、一致:
Public Property Get Number() As Integer
Number = this.Number
End Property
Public Property Let Number(ByVal value As Integer)
this.Number = value
End Property
Public Property Get Account() As Integer
Account = this.Account
End Property
Public Property Let Account(ByVal value As Integer)
this.Account = value
End Property
Public Property Get AccountType() As String
AccountType = this.AccountType
End Property
Public Property Let AccountType(ByVal value As String)
this.AccountType = value
End Property
属性Get
成员返回此属性。PropertyName
和属性允许成员分配此属性。PropertyName
始终带有提供的值。如果属性需要是非Get only的对象类型,则您需要提供属性集成员:
Private Type TData
'...
SomeObject As Object
End Type
Private this As TData
Public Property Get SomeObject() As Object
Set SomeObject = this.SomeObject
End Property
Public Property Set SomeObject(ByVal value As Object)
Set this.SomeObject = value
End Property
避免取消权限、前缀和不可读/无意义的名称,对公共成员使用PascalCase
,支持一致性,无论做什么,都要避免在公共类成员的名称中使用下划线-否则,开始使用Implements
的那一天就是代码停止编译的那一天uld始终清晰可见。删除下划线,您正在循环返回。let是您进入代码变量声明的第2行和第3行的方式,其中有下划线?我删除了let过程下t_acct、t_numb和t_类型中的下划线,它成功运行,但没有将其设置为任何值-它是still 0(0不在相关单元格中)。我尝试删除其他下划线,但它们返回了错误(大多数情况下是“无法分配给只读属性,当然,删除两个下划线会导致原始问题除外)啊哈,这个私有类型的习惯用法非常有趣。虽然我没有立即看到它的其他好处,但我可以想象。它已经允许私有字段和属性getter/letters具有完全相同的名称。而这个名称,对C++/Java程序员来说是一个极具挑战性的选择!很好。将采用@A.S.H the immedia好处是命名的一致性,这使得错误的代码看起来是错误的;另一个可能不太明显的好处是,序列化变得不需要动脑筋——你只需Put\fn,这就完成了!在C中,我使用private readonly int\u someInt;
和public int-someInt{get{return someInt;}
-我只在需要引用类实例时才在C#中使用this
。这几乎是不可能的(与VBA的Me
一样,仔细想想)。真的很有趣。你应该考虑在有时间的时候,通过一些专门的线程来分享它的好处的全面讨论。这不仅仅是一个问题的简单答案。谢谢分享。@a.s.H一个尚未实现的Rubberduck功能将是一个重构-我想利弊可以在那里讨论…我会有一次,我可能会在Rubberduck新闻博客上写一些关于它的东西,谢谢你的想法!@A.S.H-我是一个为私人成员使用类型的转化者(除了这个部分)。这个。数字看起来像是我C#眼睛的递归-我选择的名字是“backing
”。
Private Type TData
'...
SomeObject As Object
End Type
Private this As TData
Public Property Get SomeObject() As Object
Set SomeObject = this.SomeObject
End Property
Public Property Set SomeObject(ByVal value As Object)
Set this.SomeObject = value
End Property