Table of content
WholeTomato

Encapsulate Field

Refactor with Encapsulate Field to restrict or filter access to a member field. Encapsulation generates methods to read and write the value of a field, in lieu of providing access to a field directly. The accessor methods are typically called "get" and "set" methods, and have public visibility. The field the accessors encapsulate is often made private.

In C/C++, encapsulation is available only from declarations of fields. In C#, encapsulation is available only from definitions. Encapsulation is not available from field references in either language.

Open the Quick Action and Refactoring menu (Shift+Alt+Q) from a symbol and select Encapsulate Field. In C/C++, open the menu from a declaration.

A dialog opens in the event you want to change default encapsulation. Accessors are named automatically per a set of rules described below. Adjust the names in the dialog if necessary. In C++, omit a getter or setter name to avoid creating the corresponding accessor.

If the field is public you have the opportunity in the dialog to adjust visibility of the encapsulated field to private or protected. The field declaration will be moved accordingly.

In C# you can also adjust the visibility of the encapsulated field to internal.  

If the field is private or protected, the accessors are created in a public section by default. You can change this by adjusting it in the dialog.

All references to the field in the current project are listed. These references will be updated automatically to use the new accessors. If you want to extend the field search to all projects or prevent updating of any references, adjust checkboxes accordingly. If you wish to prevent updating of any references, uncheck the top-level box, i.e. the one associated with the current project.

After encapsulating, the parameter type of the set accessor and return type of the get accessor will be type of the original field.

Names of Accessors

The pattern of the variable to be encapsulated partly determines the default names of the accessors.

Pattern of Variable to be Encapsulated Variable Example Behavior Default Accessor
[lower-case letter]_[prefix][any letter]* m_nItemsCount Prefix removed ItemsCount()
[lower-case letter][upper-case letter][any letter]* hWindow Make non-Hungarian Window()
_*[upper-case letter][any letter]*_* __inStream Leading/trailing underscores removed InStream()
[lowercase letter][any letter]* datastream First letter capitalized Datastream()
[uppercase letter][any letter]* Datastream Prompt user for name of accessor  

Visual Assist also scans the VA Snippet for Encapsulate Field for $GeneratedPropertyName$. If two occurrences of the reserved string are found, adjoining text is used in default accessor names. (The presence of "void" determines the setter.) For example, the following in the VA Snippet causes Get and Set to be prepended to default accessor names:

Get$GeneratedPropertyName$
Set$GeneratedPropertyName$

Format of Accessors

Edit the VA Snippet for Encapsulate Field to modify the format and code of the accessors created. Separate VA Snippets exist for C++ and C#.

If you delete the required VA Snippet and invoke Encapsulate Field, Visual Assist recreates the default VA Snippet.

Location of Accessors

In C/C++, the accessor methods are placed in the header file with the declaration. Leave the accessors in the header file for inline execution.

If you prefer implementations in a source file, follow Encapsulate Field with two invocations of Move Implementation to Source File; only declarations will remain in the header file.

Use the Navigate commands of Visual Assist to jump between a header file and source file after moving implementations. Immediately after a move, return to the header file with Alt+Left. Return to the source file with Alt+Right. Use also Open Corresponding File (Alt+O) to jump between the two files.

References

Most simple and complex references are updated properly. Auto-decrement and increment expressions can be complex because they need to set and get values.

Encapsulate Field updates the complex references properly.

Encapsulation of an Array

In C/C++, encapsulation of an array or char * may require subsequent modification of the accessor method that writes the array, e.g. use of memcpy() or strcpy(). Additionally, references must be updated manually.

In C#, encapsulation of an array and its references are automated.

Encapsulation of an Object

Encapsulation of a field that is an object can result in errant code if you had referenced the field using &.

Updated references may retrieve the address of an accessor instead of the encapsulated object.

The compiler should warn you of such unusual cases, and you should resolve the conflict manually. One option to consider, albeit only after consideration of other references, is to update the accessor to reference form.

References that Guard

If references guard access to a field, consider moving the guards into the newly created accessors and simplifying the references.

Visual Assist build 2076 and older

After encapsulation, the original field remains intact, only default accessors names are available, and references are not updated.

The pattern of the variable and the VA Snippet for Encapsulate Field determine accessor names. You are not presented a dialog in which you can modify default names. Edit the VA Snippet if you want to adjust the default for all encapsulations.

Change existing references manually so they use accessors. Pass an argument to an accessor to set the value of an encapsulated field, and use a return value to get its value. Rewrite constructs such as increment.

Use Find References to locate all places in your code that require updating before renaming an encapsulated field.

Force callers outside of your class to use accessors by changing visibility of the accessors to private.

Force code within your class to use accessors by renaming an encapsulated field—after updating references—so compilation fails to resolve references to the old name. After using Find References to verify that the only references to the old name are those within the accessors, eliminate your old name with Rename.