I have discovered another source of documentation from the RubberDuck git repository which contains some descriptions of the refactoring options. Here is the link:
Refactorings · rubberduck-vba/Rubberduck Wiki · GitHub
According to this page, the Encapsulate Field Refactoring entry is:
Select a module variable (aka “field”) to make Private
and expose a Property Get
and Property Let/Set
accessors for.
I am going to setup a public variable in some code so I can try it out. Here is my module before the refactor with a single public variable I called EncryptionType as a string:
Option Compare Database
Option Explicit
Implements IHAL_Encryption
Public EncryptionType As String
Private Function IHAL_Encryption_decrypt(sEncryption As String, sKey As String) As String
Debug.Print TestFunction("Two", "One", "Four")
End Function
Private Function IHAL_Encryption_encrypt(sInput As String, sKey As String) As String
Debug.Print TestFunction("Second", "First", "Four", "Three")
End Function
Private Function TestFunction(Param2 As String, Param1 As String, Optional Param4, Optional Param3) As String
End Function
I will first re-run the RubberDuck parser as always to refresh the RubberDuck Refactoring capabilities. Then I can Right click on the line with the declaration and get this menu:
And when I click on Encapsulate Field I get this dialog box:
This is nice. I like that it shows me what it’s about to do and that gives me some additional ideas. What if I have a block of public variables in the class? It looks like I could do more than 1 at a time, which is pretty cool. And I want to use them in a function to see how it will handle existing references to the public variable. Let’s try this and see what it does:
Option Compare Database
Option Explicit
Implements IHAL_Encryption
Public EncryptionType As String
Public EncryptionID As Long
Public FileManager As Object
Private Function IHAL_Encryption_decrypt(sEncryption As String, sKey As String) As String
Debug.Print TestFunction("Two", "One", "Four")
End Function
Private Function IHAL_Encryption_encrypt(sInput As String, sKey As String) As String
Debug.Print TestFunction("Second", "First", "Four", "Three")
End Function
Private Function TestFunction(Param2 As String, Param1 As String, Optional Param4, Optional Param3) As String
Set FileManager = CreateObject("Scripting.FileSystemObject")
EncryptionType = "MyType"
Debug.Print EncryptionType
EncryptionID = EncryptionType
End Function
I found that by clicking on either a reference to the variable in the function or the declaration of the variable, the Encapsulate Field becomes active. When you select any variable, that variable will be auto-selected in the dialog, with the opportunity to choose other variables also:
Just selecting the single variable, I get the resulting code:
Option Compare Database
Option Explicit
Implements IHAL_Encryption
Private encryptionType1 As String
Public EncryptionID As Long
Public FileManager As Object
Public Property Get EncryptionType() As String
EncryptionType = encryptionType1
End Property
Public Property Let EncryptionType(ByVal RHS As String)
encryptionType1 = RHS
End Property
Private Function IHAL_Encryption_decrypt(sEncryption As String, sKey As String) As String
Debug.Print TestFunction("Two", "One", "Four")
End Function
Private Function IHAL_Encryption_encrypt(sInput As String, sKey As String) As String
Debug.Print TestFunction("Second", "First", "Four", "Three")
End Function
Private Function TestFunction(Param2 As String, Param1 As String, Optional Param4, Optional Param3) As String
Set FileManager = CreateObject("Scripting.FileSystemObject")
EncryptionType = "MyType"
Debug.Print EncryptionType
EncryptionID = EncryptionType
End Function
The reference to the public variable in “TestFunction” remains as is, but that is fine, it will use the public property instead.
It’s nice that you can choose multiple Public variables in the dialog and do many at once.
Using the “Wrap Fields in Private Type” option will group all selected Public options and convert them to an internal user defined type and sets the private variable “this” to an instance of the new type.
This allows you to reference your private variables as this.VariableName. I like that option. It’s similar to what Alessandro Grimaldi does in his VBA code to allow usage of autocomplete for all variables within the private internal scope of the class.
When you select each individual Member line, you can also change the name of the Public facing property for the class and if you check “Read Only” then it will only create a public getter and not a setter. If you choose to do this and you are setting the Public variable in your code inside the class, it will change the reference to set the internal private variable.
I suppose that this refactoring will also change any references to your object in external code, although I haven’t specifically tested for that in what I’m doing here.