【问题标题】:Class "let" stuck in infinite loop类“让”陷入无限循环
【发布时间】:2017-02-06 18:53:41
【问题描述】:

请原谅代码中的任何愚蠢错误,因为这是我第一次尝试使用类,而且我在网上找不到任何教程将它放在像我这样的傻瓜的真正、真正简单的术语中。我尽力遵循https://msdn.microsoft.com/en-us/library/aa716315(v=vs.60).aspx 的 MS 指南,但我并不真正理解我在做什么,这使得我很难解释我应该改变什么。

我正在尝试创建一个存储三段数据、两个整数和一个字符串的类。我把它放在一个名为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

(当然,这不是所有的代码,而只是调用它的部分)

我有 Option Explicit 和所有有趣的东西,一切都编译得很好,但是当它到达函数 sn-p 的第二行时,它试图使 t_info.t_acct 等于某个东西,它会前往Let 那个函数,并一直留在那里……永远。具体来说,它在

之间反弹
Public Property Let t_acct(ByVal newval As Integer)
    t_acct = newval

永远。为什么是这样?如何使其设置(错误,让)t_acct 等于我想要的?

【问题讨论】:

  • 去掉下划线,你正在循环回来。让你进入代码变量声明的第二和第三行
  • 哪个下划线?我删除了 let 程序下的 t_acct、t_numb 和 t_type 中的下划线,它运行成功,但它没有将它设置为等于任何值 - 它仍然是 0(0 不在有问题的单元格中)。我尝试删除其他下划线,但它们返回错误(主要是“不能分配给只读属性,当然删除两个下划线会产生原始问题)

标签: vba excel


【解决方案1】:

您的问题在这里:

Public Property Let t_acct(ByVal newval As Integer)
    t_acct = newval
End Property

那应该是分配封装的字段 (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

有些人可能会争辩说this 让一切都变得如此混乱,因为this(私有字段)不是Me(对象实例),而在其他语言中this 指的是对象实例等等 -如果它让你感到困惑,那就给它起任何你喜欢的名字(backingencapsulated 也很好!)。

现在所有属性都变得清晰且一致:

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

Property Get 成员返回 this.ThePropertyNameProperty Let 成员 assign this.ThePropertyName 与提供的 value - 总是。如果属性需要是非 get-only 的对象类型,您需要提供 Property Set 成员:

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 的日子是您的代码停止编译的那一天。遵循这一点,您的课程模块应该始终清晰。

【讨论】:

  • 啊哈,这个私有类型的习语很有趣。虽然我没有立即看到它的额外好处,但我可以想象。它已经允许私有字段和属性 getter/letters 具有完全相同的名称。还有this 这个名字,对于 C++/Java 程序员来说是一个具有挑战性的选择!好的。将采用。
  • @A.S.H 直接的好处是命名的一致性,这使得错误代码,看起来不对;另一个可能不太明显的好处是,序列化变得轻而易举 - 你只需 Put#fn,,this 就完成了!在 C# 中,我使用 private readonly int _someInt;public int SomeInt { get { return _someInt; } } - 当我 需要 引用类实例时,我只在 C# 中使用 this .. 这几乎从不(与 VBA 的 @987654347 相同@,考虑一下)。
  • 真的很有趣。当你有时间时,你应该考虑通过一些专门的线程来分享关于它的好处的全面讨论。这不仅仅是对问题的简单回答。感谢分享。
  • @A.S.H - 我是使用私有成员类型的转换者(this 部分除外)。 this.Number 看起来像对我的 C# 眼睛的递归 - 我选择的名称是“backing”。
  • 我可以为 encapsulated 妥协并称之为胜利 =)
猜你喜欢
  • 2020-05-13
  • 1970-01-01
  • 2013-03-17
  • 2021-02-15
  • 2022-01-23
  • 2021-01-23
相关资源
最近更新 更多