【问题标题】:How to prevent showing backing private fields of class properties in the Locals window?如何防止在 Locals 窗口中显示类属性的支持私有字段?
【发布时间】:2021-12-02 13:05:04
【问题描述】:

虽然是一位经验丰富的 VBA 程序员,但这是我第一次制作自己的类(对象)。我很惊讶地看到所有属性在 Locals 窗口中都是“重复的”。一个小例子(在'End Sub'处中断):

' Class module:
Private pName As String

Public Property Let Name(inValue As String)
    pName = inValue
End Property
Public Property Get Name() As String
    Name = pName
End Property

' Normal module:
Sub Test()
    Dim objTest As cTest
    Set objTest = New cTest
    objTest.Name = "John Doe"
End Sub

为什么 NamepName 都显示在 Locals 窗口中?我能以某种方式摆脱pName吗?

【问题讨论】:

  • 它只是试图通过在您调试时向您展示价值来提供帮助。 pName 是私有的,不会通过 objTest 暴露给调用者。

标签: vba class


【解决方案1】:

正如 cmets & answers 已经说过的,这只是 VBE 有帮助。

但是,如果您发现在 locals 工具窗口中列出私有字段和公共成员很吵,有一种方法可以很好地清理它 - 这里我将 Test 过程放在 @987654324 中@,并离开了名为Class1的类:

那么这里发生了什么? this 是什么?

这里是Class1

Option Explicit

Private Type TClass1
    Name As String
    '...other members...
End Type

Private this As TClass1

Public Property Get Name() As String
    Name = this.Name
End Property

Public Property Let Name(ByVal value As String)
    this.Name = value
End Property

该类只有1个私有字段,一个名为this的用户定义类型值,包含所有封装的数据成员。

因此,属性的基础字段被有效隐藏,或者更确切地说,它们都重新组合在 this 下,因此除非您想看到它们,否则您不会看到基础字段值:

另外一个好处是,您不再需要任何伪匈牙利语前缀,属性的实现非常清晰,并且最好的属性具有与其支持字段完全相同的标识符名称。

【讨论】:

  • 喜欢这个想法,是时候重写我所有的类来实现它了。
  • @BSlater 这样做的副作用是您会发现它还将对象状态序列化为二进制文件,就像在公园散步 =)
【解决方案2】:

所有检查窗口不仅向您显示对象的公共界面,还向您显示它们的私有成员。 AFAIK,您对此无能为力。

认为这是一个很好的功能,可以在调试时获得更多见解。

根据我的经验,这在现实世界的对象中不是什么问题,因为它们往往具有更多的字段和属性。假设命名一致(如您的示例所示),字段和属性很好地组合在一起。

【讨论】:

    【解决方案3】:

    如果你真的不想看到 Mathieu 的 This,你可以把它包装成一个函数。这有点复杂,可以使用

    1. 将数据存储在公共变量中的第二个类。这将比 Mattieu 的实现稍慢
    2. 使用键访问数据的集合对象。这不需要在项目 exporer 的“类模块”列表中增加额外的混乱,但如果您快速连续地重复调用 This 会慢一点

    下面给出了每个示例。如果你打破了类的初始化函数,你可以将me添加到监视窗口,并且只会列出Name属性

    使用 2 个对象示例

    插入一个类模块并将其命名为:InvisibleObjData

    Option Explicit
    Public Name As String
    Public plop
    
    Private Sub Class_Initialize()
        Name = "new"
        plop = 0
    End Sub
    

    插入一个类模块并将其命名为:InvisibleObj

    Option Explicit
    
    Private Function This() As InvisibleObjData
        Static p As New InvisibleObjData 'static ensures the data object persists at successive calls
        Set This = p
    End Function
    
    Private Sub Class_Initialize()
        This.Name = "invisible man":  Debug.Print Name
        Me.Name = "test":             Debug.Print Name
        This.plop = 111:              Debug.Print This.plop
    End Sub
    
    Property Let Name(aname As String): This.Name = aname:     End Property
    Property Get Name() As String:           Name = This.Name: End Property
    
    '_______________________________________________________________________________________
    ' in the immediate window type
    '
    '    set x=new invisibleObj
    

    如果您不喜欢将类拆分为两个对象,可以使用“包装”的集合对象生成类似的行为:

    插入一个类模块并将其命名为:InvisibleCol

    Option Explicit
    
    Private Function This() As Collection
        Static p As New Collection
        'static ensures the collection object persists at successive calls
        'different instances will have different collections
        'note a better dictionary object may help
        Set This = p
    End Function
    
    Private Function add2this(s, v)
       'a better dictionary object instead of the collection would help...
        On Error Resume Next
        This.Remove s
        This.Add v, s
    End Function
    
    Private Sub Class_Initialize()
        add2this "name", "invisible man":  Debug.Print Name
        Me.Name = "test":                       Debug.Print Name
        
        add2this "plop", 111
        Debug.Print This("plop")  ' use the key to access your data
        Debug.Print This!plop * 2 ' use of the BANG operator to reduce the number of dbl quotes
                                  ' Note: This!plop is the same as This("plop")
    End Sub
    
    Property Let Name(aname As String): add2this "name", aname: End Property
    Property Get Name() As String:            Name = This!Name: End Property
    
    
    '_______________________________________________________________________________________
    ' in the immediate window type
    '
    '    set x=new invisibleCol
    

    【讨论】:

      猜你喜欢
      • 2015-05-22
      • 2013-01-26
      • 2017-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      相关资源
      最近更新 更多