Login

Username:

Password: 

Join us Now |  Forgot Password? | Forgot UserName?

C#

Learn step by step



Encapsulation

Encapsulation, in the context of C#, refers to an object's ability to hide data and behavior that are not necessary to its user. Encapsulation enables a group of properties, methods and other members to be considered a single unit or object.
The following are the benefits of encapsulation:

  • Protection of data from accidental corruption
  • Specification of the accessibility of each of the members of a class to the code outside the class
  • Flexibility and extensibility of the code and reduction in complexity
  • Lower coupling between objects and hence improvement in code maintainability

Encapsulation is used to restrict access to the members of a class so as to prevent the user of a given class from manipulating objects in ways that are not intended by the designer. While encapsulation hides the internal implementation of the functionalities of class without affecting the overall functioning of the system, it allows the class to service a request for functionality and add or modify its internal structure (data or methods) to suit changing requirements.
Encapsulation is also known as information hiding.

Type Member Access Modifiers

An access modifier allows you to specify the visibility of code outside a type or assembly. Access modifiers can be applied to either types or type members. A later section on Type Access Modifiers discusses modifiers that can be applied to types. This section discusses those modifiers that apply to type members and how they affect visibility.

Generally, you should hide the internal state of your object from direct access from outside code. Then implement other members, such as methods and properties, that wrap that state. This allows the internal implementation of the state to change at will, while the members wrapping the state can still return a representation of the state that doesn't change. This means that outside code will access your object via members that wrap state and be guaranteed that the type of information extracted is consistent. Additionally, because external code doesn't have access to the internal state of your object, they can't alter that state in an inconsistent manner that could break the way your object works.

The first step in encapsulating object state is to determine what type of access that outside code should have to the members of your type. This is performed with access modifiers. The type of access granted varies from no external access at all to full public access and a few variations in between the extremes. Table 19-1 lists all of the type member access modifiers and explains their meaning.

Access Modifier Description (who can access)
private Only members within the same type. (default for type members)
protected Only derived types or members of the same type.
internal Only code within the same assembly. Can also be code external to object as long as it is in the same assembly. (default for types)
protected internal Either code from derived type or code in the same assembly. Combination of protected OR internal.
public Any code. No inheritance, external type, or external assembly restrictions.
Members to public Access

You've seen the public access modifier used in earlier parts of the C# Tutorial. Any time the public access modifier is used on a type member, calling code will be able to access the type member. If you make your type member public, you are giving everyone permission to use it. Listing 19-1 shows an example of using the public access modifier on a method.

using System;
class BankAccountPublic
{
public decimal GetAmount()
{
return 1000.00m;
}
}

The GetAmount() method is public meaning that it can be called by code that is external to this class. Now, you can write the following code, elsewhere in your program, to use this method:

BankAccountPublic bankAcctPub = new BankAccountPublic();
// call a public method
decimal amount = bankAcctPub.GetAmount();

All you need to do, as shown above, is create an instance of the class that contains the method and then call the method through that instance. Because it is public, you won't have a problem. Remember that the default access for a type member is private, which we'll talk about next. This means that if you forget the public modifier, and didn't use any modifier at all, you would receive a compiler error.

Members with private Access

A private type member is one that can only be accessed by members within the same type. For example, if the BankAccount class has a private member, only other members of the BankAccount class can access or call that member.

Although the default access for type members is private, I prefer to be explicit about my intentions when declaring type members and include the access modifier, rather than rely on defaults. I think it makes the code easier to read and makes it clear to other developers what my true intention is. Listing 19-2 shows how to use the private access modifier and offers an example of why you would want to use it.

using System;
class BankAccountPrivate
{
private string m_name;
public string CustomerName
{
get { return m_name; }
set { m_name = value; }
}
}

It's common to encapsulate the state of your type with properties. In fact, I always wrap my type state in a property.you can see how the name of the customer is held in the m_name field, but it is wrapped (encapsulated) with the CustomerName property. Because m_name is declared as private, code outside the BankAccountPrivate class can't access it directly. They must use the public CustomerName property instead.

Now you can change the implementation of m_name in any way you want. For example, what if you wanted it to be an ID of type int and the CustomerName property would do a search to find the name or what if you wanted to have first and last name values that the CustomerName property could concatenate. There are all kinds of things happening to your code in maintenance that will causes implementation to change. The point is that private members allow the implementation to change without constraining the implementation or causing rippling effects throughout your code base that would have occurred if that external code had access to the members of your type.

The private and public access modifiers are at the two extremes of access, either denying all external access or allowing all external access, respectively. The other access modifiers are like different shades of gray between these two extremes, including the protected modifier, discussed next.

protected Access Modifier

In some ways, the protected access modifier acts like both the private and public access modifiers. Like private, it only allows access to members within the same type, except that it acts like public only to derived types. Said another way, protected type members can only be accessed by either members within the same type or members of derived types.

In the case of closing an account, there are several things that need to be done like calculating interest that is due, applying penalties for early withdrawal, and doing the work to remove the account from the database. Individually, you don't want any code to call methods of the BankAccount class unless all of the methods are called and each method is called in the right order. For example, what if some code called the method to delete the account from the database and didn't calculate interest or apply penalties? Someone would lose money. Also, if the calling code were to delete the account first then the other methods would run into errors because the account information isn't available. Therefore, you need to control this situation and Listing 19-3 shows how you can do it.

using System;
class BankAccountProtected
{
public void CloseAccount()
{
ApplyPenalties();
CalculateFinalInterest();
DeleteAccountFromDB();
}
protected virtual void ApplyPenalties()
{
// deduct from account
}
protected virtual void CalculateFinalInterest()
{
// add to account
}
protected virtual void DeleteAccountFromDB()
{
// send notification to data entry personnel
}
}

The most important parts that the CloseAccount method is public and the other methods are protected. Any calling code can instantiate BankAccountProtected, but it can only call the CloseAccount method. This gives you protection from someone invoking the behavior of your object in inappropriate ways. Your business logic is sound.

If you only wanted the BankAccountProtected class to operate on its own members, you could have made the protected methods private instead. However, this code supports a framework where you can have different account types such as Savings, Checking, and more. You will be able to add new account types in the future because the BankAccountProtected class is designed to support them with protected virtual methods. Listings 19-4 and 19-5 show you the SavingsAccount and CheckingAccount classes that derive from the BankAccountProtected class.

Access Modifiers for Types

So far, the discussion of access modifiers has only applied to the members of types.  However, the rules are different for the types themselves. When talking about types, I'm referring to all of the C# types, including classes, structs, interfaces, delegates, and enums. Nested types, such as a class defined within the scope of a class, are considered type members and fall under the same access rules as other type members.

Types can have only two access modifiers: public or internal. The default, if you don't specify the access modifier, is internal. Looking at all of the classes used in this lesson, you can see that they are internal because they don't have an access modifier. You can explicitly specify internal like this:

internal class InternalInterestCalculator
// members go here
}

Perhaps the InternalInterestCalculator, shown above, has special business rules that you don't want other code to use. Now, it is in a class library of its own and can only be accessed by other code inside of that same class library (DLL).

Note: To be more specific, internal means that only code in the same assembly can access code marked as internal. However, discussing the definition of an assembly is outside the scope of this lesson, so I am simplifying the terminology.

If you declared a class inside of a class library that you wanted other code to use, you would give it a public access modifier. The following code shows an example of applying the public access modifier to a type:

public class BankAccountExternal
{
// members go here
}


Related Videos