You implement a class by combining both state and behavior together in a well-defined unit, which is the implementation of a specified class type. The data members (variables, buffers, etc.) and properties represent the object state for a given class. The methods and events represent the object behavior for a given class, which define how a class, and code outside the class, can interact with its own data members and properties, and any other data it can access. Objects invoke each others’ behavior by sending messages to each other according to the interface defined by each object’s type. A message, in this context, identifies a specific unit of behavior defined for an object. Thus, you can send a message to an object by calling a method on that object or by publishing a class event that invokes an event handler in that object.
Note: A message is not necessarily a physical data packet, but is a concept that conveys the idea that one object is using some means to request that an action be performed on the part of a second object, which involves a specified subset of the second object’s data.
Through the well-defined interface of its class type, an object can satisfy its contract to class consumers while keeping details of its implementation private. The general mechanism that a class uses to provide access to resources according to its contract, while maintaining the privacy of its implementation, is referred to as encapsulation. Because of the goal to maintain the privacy of a class’s implementation, encapsulation is also known as information hiding.
Thus, depending on its interface, a class can allow some of its code and data to be accessible from outside the class hierarchy and some of it to be inaccessible. With complete encapsulation, you hide all data of a class from direct access, and you define a set of properties, methods, and events as the interface to that data. By enforcing access to the data of a class through such a well-defined interface, you can change the implementation of the class at any time without affecting any other code that accesses this interface.
To help define a class’s interface, you can define an access mode for every class member (private, protected, or public) that controls where and how the member can be accessed. Thus, a private method can be accessed within the class where it is defined. The private method of an instance can also be accessed by another instance of the same class. A protected method can be accessed within the class where it is defined and within any class that inherits from that class (see the ). An instance of a class can access the protected member of a second instance of a class that is at the same level or in a super class in the class hierarchy. A public method can be accessed within the class where it is defined, from within any class that inherits from that class, and from outside any instance (object) of that class (that is, from within a procedure or a class instance that is outside the class hierarchy where the public method is defined). You can similarly define private, protected, and public data members, properties, and events of a class, and you can further define properties so that they can be read and written according to different access modes.
The following figure shows a simple example of encapsulation.
Figure 1. Encapsulation example
In this figure, ClassA defines DataA as private. DataA can only be accessed from within the class definition or by an instance of that class. ClassA also defines a public MethodA that provides indirect access to DataA through the method’s parameter, ParmA. Thus, after instantiating the class, the pseudo-code fragment uses ClassA as shown with the numbered arrows:
1. Invokes its MethodA on the ClassA instance referenced by ObjectA.
2. MethodA assigns the value of DataA to ParmA, which the fragment returns as an output parameter.
3. Using DataX, the fragment then accesses the value of DataA without actually accessing DataA, itself.
So, you can define a class interface so that some of its data members can be accessed directly and others accessed only indirectly, through methods of the class. In addition, properties, which allow you to define different access modes for read and write access, can also be defined as read-only (so they cannot be written) and write-only (so they cannot be read). You can define special methods for properties that execute when they are read or written, which effectively hides the implementation of the data they access. Therefore, to define a class with complete encapsulation, you would define all of its data members as private or protected, and define public properties, methods, and events to access any of that data from outside the class.