CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf ·...

34
10-1 CHAPTER 10 ENCAPSULATION In the Essentials section you will learn: What encapsulation is What benefits encapsulation provides What accessibility level the public and private access modifiers provide What a class interface is How to use properties and accessor methods What a class constructor is How to dynamically set an object’s state at instantiation In the Bonus section you will learn: What the program stack and managed heap are How memory is managed What a garbage collector is and what function it serves Encapsulation is one of the cornerstone design principles of object-oriented programming. The essential principle of encapsulation is that an application’s logic should be divided into well- organized modules that are each self-contained and self-sufficient. This division allows developers an increased control of the application’s state. In addition, encapsulation facilitates reuse of code, thus reducing the amount of redundant code within an application. The benefits of encapsulation include modular code that is ultimately easier to debug, deploy, support and reuse.

Transcript of CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf ·...

Page 1: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-1

CHAPTER 10

ENCAPSULATION In the Essentials section you will learn:

What encapsulation is What benefits encapsulation provides What accessibility level the public and private access modifiers provide What a class interface is How to use properties and accessor methods What a class constructor is How to dynamically set an object’s state at instantiation

In the Bonus section you will learn: What the program stack and managed heap are How memory is managed What a garbage collector is and what function it serves

Encapsulation is one of the cornerstone design principles of object-oriented programming. The essential principle of encapsulation is that an application’s logic should be divided into well-organized modules that are each self-contained and self-sufficient. This division allows developers an increased control of the application’s state. In addition, encapsulation facilitates reuse of code, thus reducing the amount of redundant code within an application. The benefits of encapsulation include modular code that is ultimately easier to debug, deploy, support and reuse.

Page 2: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-2 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

ESSENTIAL TOPICS ENCAPSULATION REVIEW

A common analogy used when discussing encapsulation is a ‘black box’. From outside the box, you cannot see what is within. While from within the box, you cannot see what is outside.

Conceptually, encapsulation refers to the practice of making information technology components self-contained. It is a very common design practice in many modern information technology disciplines – not only object-oriented programming.

When encapsulation is referred to in this book, it will be the context typically used in object-oriented programming: the combining of data (properties) and means of manipulating that data (methods) within the definition of each class so that objects of that class are self-contained.

One of the primary purposes of encapsulation, data hiding, was introduced in Chapter 1. Data hiding is a means of increasing control over an application’s state by restricting direct access to the internal representation of state: the application’s data. Access to state is often gained only indirectly through the use of predefined object methods.

One of the chief benefits of encapsulation is that code becomes modular because code within one class has little or no dependencies on code in other classes. This increases the ease with which code can be reused. Discreet, self-contained modules of code are also easier to test, easier to debug, and easier to deploy than non-modular code.

CREATING YOUR OWN CLASS So far, the lessons and coding exercises in this textbook have dealt solely with applications containing a single custom frmMain class. All of the logic necessary for each application to function has been stored in this single class. Creating applications in this manner has allowed you to develop fundamental programming skills. However, as the requirements of a software application increase, the number of classes necessitated also increases. In fact, it is not uncommon to find modern, enterprise-class applications containing thousands of classes.

Throughout the remainder of this chapter, we will be creating a simple Contact List application (the GUI is shown in Figure 10-1). This application will collect, organize, and display contact information for individuals that have been input by the user. Our application will require the creation of several custom classes, all of which will be contained in a single Visual Studio project. This version of the application will store this data only in memory. However, subsequent chapters in the textbook will show you how to store the application’s data in files and databases (a process known to as persistence).

Page 3: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-3

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Figure 10-1 GUI of the Contact List application

Create the ContactList Project Create a new project in Visual Studio (refer to Chapter 2 if you need to review the proper technique to do so). Name the project ContactList.

Add a New Code File to the Project If Solution Explorer is not visible in Visual Studio, make it so. This can be done by selecting View Solution Explorer as shown in Figure10-2.

Figure 10-2 Enabling the Solution Explorer Pane

Within Solution Explorer, right-click on the ContactList project. Select Add New Item as shown in Figure 10-3. Do not select Add Class. Adding a new class directly into your project will include extraneous code that is of no use to you. In addition, as with all lessons in this textbook, the authors believe that you will learn more by personally writing code than if you allow an IDE to create it for you.

Page 4: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-4 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

Figure 10-3 Adding a New Item

After indicating to Visual Studio that you would like to add a new item to your project, a dialog box will be shown from which to select the item’s specific type. As shown below in Figure 10-4, select Code File from the templates provided. Name the code file clsContact.cs, then click the Add button.

Figure 10-4 Add New Item Dialog Box If you have completed these steps successfully, a file named clsContact.cs should have been created and added to your ContactList project. You can confirm this by again checking Solution Explorer as shown in Figure 10-5.

Page 5: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-5

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Figure 10-5 Project ContactList after adding clsContact

Naming Standards for Class Files In the previous step, we named the code file clsContact.cs. Later in this chapter, we will create another class file named clsPhoneNumber.cs. Both were named according to specific coding standards. As with all your code, you should consistently follow the appropriate naming standards (see Appendix B) when creating a C# class. The standards preferred by the authors of this textbook use a three-character prefix (cls) to identify the file as containing code that defines a class from which objects can be instantiated. Recall that the suffix .cs identifies the file type as a C# source code file. The characters between the prefix and the suffix should be written in camel-back notation, and describe the purpose of the class.

Build the Empty Code File into a C# Class File The clsContact.cs file has been created, but is currently empty. Add the following code to clsContact.cs, then save the file.

Figure 10-6 clsContact (empty)

You have just completed the steps necessary to add a new class to your project. At this point, the project should build and even run – although it won’t yet “do” anything while running. That comes next.

1 using System; 2 3 public class clsContact 4 { 5 6 }

Page 6: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-6 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

ACCESS SPECIFIERS Now that your application has more than one class, it is an appropriate time to discuss the topic of access specifiers. Access specifiers are sometimes referred to as access modifiers, and control the amount of access classes have to each other’s members.

The term “class member”, or simply “member”, refers to any method or piece of class-scope data contained in the class. Class members you are already familiar with include variables, constants, and methods. Later in the chapter you will learn about an additional class member: properties. Sometimes the term “type member” or “data member” is used to identify only those class members that maintain an object’s state (i.e., hold a value). Class members that are considered type members are variables, constants, and properties. Note also the requirement that the variable or constant be class-scope. This is because data members hold the object’s state. In contrast, variables and constants having only local scope are typically used as temporary containers for intermediate values used within a method’s logic. As such, local-scope variables and constants do not maintain the object’s state, and because of this they are not considered object data members.

All class members have a specified accessibility, even if it is not explicitly set by the developer (i.e., they possess the default level of accessibility). The two most common access specifiers are public and private. Before we begin a technical discussion on public and private specifiers, an analogy might help to illustrate the concept.

Analogy: a Local Savings and Loan Bank A local bank has a lobby which is open to the public. In the lobby can be found pamphlets describing the checking and savings account options available at the bank, as well as types of loans the bank offers. These publicly accessible pamphlets are freely available to anyone who chooses to pick them up, no matter if they are clients of the bank, bank employees, or even just someone who has walked in off the street. However, the bank also has a private vault in which it keeps its cash reserves. The vault and its contents are private, and as such available only to bank employees, while the general public has no access.

Private Access Specifier Class members that are specified as private are directly accessible only to logic residing within the same class as the member itself. This means that logic residing in other classes cannot directly access the private member. For example, if we create a class scope variable in our clsContact class to hold the person’s first name – and that variable was specified as private (shown in Figure 10-7) – then this variable would be inaccessible to logic residing in all other classes.

Figure 10-7 Explicitly Setting a Class Member’s Accessibility to Private

As previously mentioned, C# defaults all class members to private accessibility unless explicitly set otherwise. So the class-scope variable shown in Figure 10-8 to hold the contact’s middle name (mMiddleName) would also be inaccessible to logic in other classes.

Page 7: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-7

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Figure 10-8 Implicitly Setting a Class Member’s Accessibility to Private Even though not required, you should always explicitly specify the accessibility of your class members. Doing so results in more explicit code that better reflects the intentions of the developer, which in turn results in code that is more easily understood, debugged, and supported.

Public Access Specifier Class members that are explicitly specified as public are directly accessible not only to logic residing within the same class, but also to logic residing in other classes. For example: if we were to create a class scope variable in the clsContact class to hold an individual’s last name – and this variable explicitly specifies public accessibility – then it would be accessible to logic residing in both our clsContact class and our frmMain class. The code in Figure 10-9 illustrates creation of a public data member.

Figure 10-9 Explicitly Setting a Class Member’s Accessibility to Public

To access the public member from another class, simply refer to it using the dot notation. The code in Figure 10-10 illustrates this technique, specifically demonstrating assignment of a value to the public member (LastName) from within a different class (frmMain).

Figure 10-10 Explicitly Setting a Class Member’s Accessibility to Public

Page 8: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-8 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

Naming Standards The accessibility of a data member is often reflected in the name of the data member. Recall the naming standards we use in this book: while local-scope variable names begin with a lowercase letter, all class-scope variables begin with an uppercase letter. Private class-scope variables are additionally prefixed by the lower case letter “m”. For example, mFirstName, mMiddleName. Public class scope variables are not assigned a prefix. See Appendix B for more information on the naming standards used in this book.

Implications of each Access Specifier What are the implications of declaring a type member private? The primary limitation is that the class member cannot be read or changed by any logic outside the class itself.

What are the implications of declaring a type member public? First, any class member within the entire application will have the ability to directly “read” the data held in the public member. Second, any class member within the entire application will have the ability to “change” the data held in the public member. Third, any class added to the application in the future will also have the ability to read and/or change the data held in the public member.

CLASS INTERFACES The implications of both public and private data member access can limit their usefulness. To overcome these limitations, another type of data member is available to developers: properties. Properties combine the best qualities of a private data member with the best qualities of a public method, and in so doing they lesson the limitations of each.

The use of properties and accessors allow developers to define tightly controlled interfaces into their classes as well as hide the state (data) of the class. It is because of this that use of class properties is a development practice considered necessary for encapsulation. Before we begin a technical discussion up properties and accessors however, continuing our bank analogy might help to illustrate the concept.

Analogy: Bank Tellers Recall the local bank from our previous analogy. The bank’s cash reserves are held in a vault accessible only to bank employees. Bank customers – who do not have access to the vault – visit the bank throughout the day and interact with bank tellers. Bank tellers – who are bank employees and thus have access to the vault – facilitate customer deposits and withdrawals. They do so, however, impose very strict limitations upon the customers. For example, a customer might have to prove identity prior to withdrawing funds, cannot withdraw more money than is actually in the account, and is required to provide the appropriate withdrawal slip. Bank Tellers also perform tasks prior to adding contents to the vault. For example, they face all bills in the same direction, create appropriately sized stacks, and then wrap them.

Properties and Accessors Properties are publically accessible data members that are implicitly coupled with pseudo-methods referred to as accessors. Accessors contain logic that is executed when the property is accessed. As accessor logic can – and often does – subsequently access a private data member, use of properties allows developers a means of providing tightly controlled indirect access of private data members to other classes.

There are two types of accessors that serve distinctly different purposes: get accessors and set accessors. The get accessor is executed when a property is “read”. Recall that this occurs when the

Page 9: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-9

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

property is on the “right” side of an assignment operation. In contrast, the set accessor is executed when a property is set or “written to”. This occurs when a property is on the left side of an assignment operation. Because of how they operate, accessors are sometimes referred to as “getter and setter operations”, or simply “getters and setters”.

Implementing Properties and Accessors The code below illustrates the implementation of a class property (FirstName) and its accessors. 3 public class clsContact 4 { 7 private string mFirstName; 36 public string FirstName 37 { 38 get 39 { 40 return mFirstName; 41 } 42 43 set 44 { 45 string temp; 46 47 // Make everything lower case. 48 49 value = value.ToLower(); 50 51 // Pull out the first letter. 52 53 temp = value.Substring(0,1); 54 55 // Build by making first letter upper case and add the rest. 56 57 value = temp.ToUpper() + value.Substring(1,value.Length - 1); 58 mFirstName = value; 59 } 60 } 121 }

Figure 10-11 Implementation of a Class Property and its Accessors Notice that the data member mFirstName is private (line 7). Notice also that this data member is “read” in the get accessor logic (lines 38 to 41), and its value “set” in the set accessor logic (lines 43 to 59).

Looking next at the accessor implementation you can see that the get accessor acts like a method. It even returns a value (line 40), and that the data type of that value is identified in the property declaration (line 36).

Similarly, the set accessor acts like a method that returns void. However, it also acts as if it receives an argument simply named value when invoked (lines 49, 53, 57, and 58). This value variable can be thought of as an implicit parameter generated by the set accessor implementation. It doesn’t need to be declared or instantiated in order to be used. In this example, the logic in the set accessor is used to ensure the name is always stored with the first character capitalized.

Page 10: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-10 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

Accessing a Property Class properties are generally defined public. As such, they are accessed using the dot notation you are already familiar with. The code in Figure 10-12 illustrates how to access a property of the clsContact class from the frmMain class.

5 public partial class frmMain: Form 6 { 23 private void btnAdd_Click(object sender, System.EventArgs e) 24 { 32 // Instantiate and populate the new Contact item. 33 34 clsContact contact = new clsContact(); 35 contact.FirstName = txtFirstName.Text; 46 } 213 }

Figure 10-12 Accessing a Class Property via its Set Accessor Notice that the property (FirstName) is on the left side of an assignment operation (line 35) – it is being assigned a value. Because of this, it is the set accessor of the LastName property that will be invoked. Furthermore, because a set accessor is being invoked, we know that an implicit parameter exists. In this case, the contents of the txtLastName textbox will be passed as an implicit argument.

Similarly, the dot notation is used when reading a property. Recall that this occurs when the property is on the right side of an assignment operation. Recall also that this invokes the property’s get accessor. The code in Figure 10-13 demonstrates how this is done, specifically illustrating how to display the FirstName, LastName, and HomePhone of the selected contact.

5 public partial class frmMain: Form 6 { 119 // Displays the property values for the selected contact. 120 private void lstContacts_DoubleClick(object sender, System.EventArgs e) 121 { 129 // Get the reference to the selected contact. 130 131 clsContact contact = (clsContact)lstContacts.SelectedItem; 132 133 // Display the contact's property values. 134 135 txtFirstName.Text = contact.FirstName; 136 txtLastName.Text = contact.LastName; 137 txtHomePhone.Text = contact.HomePhone.ToString(); 141 } 213 }

Figure 10-13 Accessing Class Properties via their Get Accessors

Page 11: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-11

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Common Uses for Properties In addition to facilitating encapsulation, many other uses for properties exist. Some of the more commonly used development techniques involving properties include:

Creating a “read-only” property Create a “write-only” property Performing validation or formatting prior to changing state Formatting data prior to returning it to the invoker Combining multiple pieces of data prior to returning it to the invoker

We have so far used properties implementing both a get accessor and a set accessor. These are referred to as “read-write” properties. However, properties are not required to implement both accessors. Those that implement only a get accessor are referred to as “read-only” properties, while those that implement only a set accessor are referred to “write-only” properties.

Performing data validation or formatting prior to changing state takes advantage of the set accessor code block. This technique was demonstrated in Figure 10-11 above. Specifically, the contact’s first name was formatted prior to being assigned to the mFirstName data member, this formatting taking place in the set accessor code block of the FirstName property.

Similarly, the get accessor code block can be used to format data prior to providing it to the invoker. The code in Figure 10-14 illustrates this technique.

3 public class clsContact 4 { 5 private string mFirstName; 29 public string FirstName 30 { 31 get 32 { 33 string firstCharacter; 34 string firstName; 35 36 firstCharacter = mFirstName.Substring(0, 1); 37 firstName = firstCharacter.ToUpper() + 38 mFirstName.Substring(1, mFirstName.Length - 1); 39 40 return firstName; 41 } 42 43 set 44 { 45 mFirstName = value; 46 } 47 } 99 }

Figure 10-14 Formatting a Return Value via the Get Accessor So far we have demonstrated only properties that have directly corresponded to a private data member. For example, the LastName property and the mLastName private data member. This does

Page 12: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-12 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

not have to be the case, however. Properties can in fact correspond to several data members, presenting a single value to code outside of the class. This technique is illustrated in Figure 10-15.

3 public class clsContact 4 { 5 private string mFirstName; 6 private string mLastName; 69 public string LastFirstName 70 { 71 get 72 { 73 return mLastName + ", " + mFirstName; 74 } 75 } 99 }

Figure 10-15 A Property that amalgamates multiple Class Members Alternately, properties do not have to correspond to any data member at all. One example of this is contact age, which is derived using the contact’s birthdate and the current system date. Figure 10-16 demonstrates the implementation of this class property.

3 public class clsContact 4 { 9 public DateTime BirthDate; 77 public byte Age 78 { 79 get 80 { 81 // Get the birth date value for the current year. 82 83 DateTime thisYearBirthDate = 84 new DateTime(DateTime.Now.Year, BirthDate.Month, BirthDate.Day); 85 86 // Calculate and return the age based on if 87 // the birth date has occurred this year or not. 88 89 if (thisYearBirthDate <= DateTime.Now) 90 { 91 return (byte)(DateTime.Now.Year - BirthDate.Year); 92 } 93 else 94 { 95 return (byte)(DateTime.Now.Year - BirthDate.Year - 1); 96 } 97 } 98 } 99 } 139 }

Figure 10-16 A Property that does not directly correspond to a Class Member

It should now be clear how useful class properties can be when designing a class’s public interface. It should also be clear how much implementation flexibility class properties can provide to developers seeking to increase control of their class’s state.

Page 13: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-13

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

GUIDELINES FOR ACCESS SPECIFIER AND PROPERTY USAGE You should now understand how to use the two most common access specifiers – public and private – to define the accessibility of your class members. You should also understand how to use properties and their accessor methods to further refine the accessibility of your class data members. But which technique or combination of techniques do you use? And when?

The authors have found the following guidelines to be both practical and useful:

If a class member (i.e., variable, constant, method, or property) is going to be used only

within its own class, it should have private accessibility. Private class members are not accessible to other classes in the program.

If a class member is going to be used by other classes in the program, it should have either public accessibility or a public property associated with it. Public accessibility allows other classes in the program to directly access the class member. Property usage allows tightly controlled, indirect access to class data members.

If the class member is a method and will be used by other classes in the program, it should have public accessibility.

If the class member to be used by other classes in the program is a variable or constant (i.e., a class data member), and benefit can be added via a property’s accessor methods, then use a property. As previously discussed, accessor methods can address data validation and data formatting needs. Accessor methods can also be used to make a class data member either read-only or write-only. Finally, accessor methods can derive a single return value from multiple class data members, or none at all. In each of these ways, a property’s accessor methods can provide benefit to a program, and usage of a property is warranted.

However, if the variable or constant is to be used by other classes in the program and will receive no benefit from a property’s accessor methods, then the variable or constant should have public accessibility. This last guideline is a very practical one, and is based on the fact that creating a property requires more code than simply specifying the accessibility of a class data member. And if that additional code provides no additional benefit to the program, the code should not be included in the program. Thus, only use properties in place of publicly accessible class members when property usage provides benefit to the program.

CREATING A NEW INSTANCE OF AN OBJECT VARIABLE By now you are familiar with creating new instances of objects in your programs. The specific terms for this are instance declaration and instantiation, and a clarified understanding of these two processes is now appropriate. Before we begin a technical discussion on instance declaration and instantiation however, let’s continue the bank analogy.

Analogy: Building a New Branch of the Bank Recall the local bank from our previous analogies. The city in which it resides has been expanding, and because of this, it has been determined that a second branch of the bank should be created in a different part of town. Once this decision has been made, the bank first needs to solicit the approval of all appropriate governmental agencies (city, state, and federal). Once these approvals have been acquired, the bank can then identify a physical location for the new branch, build a physical

Page 14: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-14 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

structure to house the new branch, and establish relationships with utility providers (e.g., power, water, internet, telephone, security, etc.) necessary for the new branch.

Opening new branches of a bank is analogous to creating a new instance of a class. Doing so requires appropriate permissions, adequate resources, and registration of relevant processes with the administering system (i.e., the computer’s operating system).

Declaration and Instantiation Using an object of any class is a two-part process. A variable needs to be defined to hold a reference to the object, and the object needs to be instantiated using the new keyword.

The following code snippet demonstrates declaration of a variable that can at some point in the future contain a reference to an object instantiated from the clsContact class:

clsContact businessContact;

Looking at the code, you probably realize that the declaration process for objects is similar to other variable declarations you have worked with. That is the data type is specified and is followed by a variable name that adheres to the C# rules for variable names. However, it is important to realize that a clsContact object is not created during the variable declaration.

The instantiation of an object in C# is simply the creation of the object in memory. It is at this point that memory is assigned to the object, and a reference to the object just created is placed in a variable. It is only after this point that the object can be “used” in the program. The following code snippet demonstrates instantiation of an instance of the clsContact class.

businessContact = new clsContact();

After instantiation, the object exists in memory. The object may then be referenced by using the variable name which points to its location in memory.

It is often convenient to combine declaration and instantiation into a single statement. The following code snippet demonstrates this technique:

clsContact businessContact = new clsContact();

Again, after instantiation the object exists in memory and may then be referenced by using the variable name that points to its location in memory.

THE INITIAL STATE OF AN OBJECT When a new object is created, all of its data members are assigned a value. The assignment can be done explicitly by the developer, or implicitly by the C# compiler. Specifically, for each and every data member in a class, the developer can:

Accept the implicit default provided by the C# compiler. Explicitly define a new default value. Provide a means of dynamically setting the value at runtime via usage of constructors.

As you can see, developers possess a great deal of flexibility with regards to both the choice of value assigned to a data member, as well as the mechanism of assignment. However, before we begin a technical discussion upon each of the techniques mentioned, an analogy might help to illustrate the concepts.

Page 15: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-15

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Analogy: Staffing a New Branch of the Bank Recall the newly created 2nd branch of a local bank from our previous analogy. All necessary governmental approvals have been acquired, a location identified, the physical structure built, and utilities have been turned on. However, the branch must still be staffed. Only after the branch has appropriately trained managers, tellers, loan officers, financial advisors, security officers, administrative assistants, and custodial personnel in place can they open their doors for business.

For some staff positions – particularly key positions such as branch manager and senior loan officer – experienced employees from other branches may be transferred in. However, staff positions necessary to bank operations that are not filled via transfer require new employees be hired and trained prior to opening of the new branch. Finally, staff positions essential to the long term operation of the branch, but not the initial opening of it – positions such as seasonal help, additional custodial staff, or redundant / cross-trained personnel – may be left vacant until well after the branch has been in operation for some time.

Implicit Default Recall from Chapter 3 all data members possess a value from the very moment of their creation. If not explicitly initialized with a value, the C# compiler will implicitly assign each data member the default value appropriate to its data type. Specifically:

Numeric types are assigned the value zero (0). The Boolean type is assigned the value false. The DateTime type is assigned the value midnight of January 1, 0001. Reference data types – including the string type – are assigned the value of null.

The following two variable declarations do not explicitly assign an initial value to the variable. Thus they accept the implicitly assigned default values for string and DateTime types respectively.

private string mContactType;

private DateTime mBirthDate;

Initialization A second means of assigning the initial state of a data member is referred to as initialization, and is a mechanism you are already familiar with. Initialization is simply including an initial value in the definition of the data member. Examples are shown in the code snippet below.

private string mContactType = "family member";

private DateTime mBirthDate = DateTime.Now;

Initialization is often used by developers to explicitly create a default value for a class data member. For example, in the above code snippet, the developer has identified that all instances of the clsContact class will be – at least initially – of contact type “family member”. Of course, since the data member is a variable, this value can be changed as the program runs.

It should be noted that data members declared constant must be initialized. If you fail to assign them an initial value during declaration, your program will not compile!

Page 16: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-16 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

Constructors The third means of assigning the initial state of data members is via use of constructors. A constructor is a class method that is automatically invoked when a new instance of that class is instantiated. Or in other words, the class constructor method is invoked each time a new object of that class is created.

Each class has at least one constructor even if you don’t code one. However, it is possible – in fact common – for classes to have multiple constructors. This is done through method overloading.

Method Overloading

Method overloading was discussed in the Bonus section of Chapter 7. If you have not yet read it, you should do so now as the remainder of Chapter 10 presumes that you already possess an understanding of the topic.

Constructor Syntax The syntax for defining a class constructor is similar – but not identical - to that of other class methods. The following rules apply to constructor syntax:

A class constructor method must have the same name as its class. A class constructor does not define a return type, not even void. A class constructor cannot return any value to the calling method.

Figure 10-17 demonstrates a class (clsContact) that contains two constructors. Notice that each constructor is named clsContact, and neither definition includes a method return type.

3 public class clsContact 4 { 11 public clsContact() 12 { 13 mFirstName = ""; 14 mLastName = ""; 15 HomePhone = new clsPhoneNumber(""); 16 MobilePhone = new clsPhoneNumber(""); 17 BirthDate = DateTime.MinValue; 18 } 19 20 public clsContact(string first, string last) 21 { 22 mFirstName = first; 23 mLastName = last; 24 HomePhone = new clsPhoneNumber(""); 25 MobilePhone = new clsPhoneNumber(""); 26 BirthDate = DateTime.MinValue; 27 } 111 }

Figure 10-17 Class containing an Overloaded Constructor

Page 17: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-17

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Invoking the Constructor The constructor method of a class is invoked each time a new instance of that class is created. The syntax to invoke the version of the constructor that requires no parameters (referred to as the default constructor) is demonstrated in the following code snippet:

clsContact familyMember = new clsContact();

The following code snippet demonstrates invoking the second version of the constructor shown above (i.e., the version that accepts three parameters).

clsContact businessAssociate = new clsContact("Jane", "Smith");

Note that it is the C# keyword new that both creates the new object, and specifically invokes the object’s class constructor. The Default Constructor As mentioned above, the default constructor for a class takes no arguments. This is true whether the default constructor is explicitly created by a developer (as shown above), or implicitly created by the C# compiler.

This latter statement may need some explanation. A default class constructor is implicitly created by the C# compiler if one is not explicitly created by the developer. The primary function of these implicitly created constructors is to assign appropriate default values to all data members during instantiation should they not be explicitly initialized.

When should a default constructor be explicitly defined and when should the implicit default constructor be accepted? If the constructor does nothing but initialize data members to default values, it is best to allow the C# compiler to implicitly generate a default constructor. Why? Because explicitly coding a default constructor which does nothing more than the implicit default constructor creates unnecessary code – code that must then be explicitly tested, debugged, and maintained. However, if additional functionality is necessary during instantiation of an object, then an explicit default constructor may be the better development choice. Common uses for Explicit Constructors The most common use for an explicit constructor is to dynamically set the value of data members at to a special value. This technique can be incorporated into explicit default constructors though the reading of environmental settings and values (e.g., network conditions, server directory structure, operating system, etc.). However, it is far more often accomplished through the use of parameterized constructors. Arguments provided at runtime can then be incorporated into the initial state of the instantiated object, as demonstrated in lines 20 through 27 of Figure 10-17.

Explicit constructors also commonly perform validation, up to and including the generation of exceptions. For example, an object that reads data from a file may validate the existence of the file during instantiation. Because of this, conditional logic is often found in explicit constructors.

Page 18: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-18 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

SOURCE CODE FOR THE PROGRAM Throughout this chapter, we have been developing an application to manage contacts. The source code for this application – the Contact List application – is shown below. Note that it is comprised of three classes: frmMain (Figure 10-18), clsContact (Figure 10-19), and clsPhoneNumber (Figure 10-20). The designer partial class (frmMain.designer) has not been included as it contains only properties associated with the GUI.

1 using System; 2 using System.Windows.Forms; 3 4 public partial class frmMain: Form 5 { 6 public static void Main() 7 { 8 frmMain main = new frmMain(); 9 Application.Run(main); 10 } 11 12 public frmMain() 13 { 14 InitializeComponent(); 15 } 16 17 private void btnAdd_Click(object sender, System.EventArgs e) 18 { 19 // Validate the input values. 20 21 if (validateInput() == false) 22 { 23 return; 24 } 25 26 clsContact contact = new clsContact(); 27 getInputValues(contact); 28 29 // Note: the listbox has DisplayMember = LastFirstName. 30 31 lstContacts.Items.Add(contact); 32 txtHomePhone.Text = contact.HomePhone.ToString(); 33 txtMobilePhone.Text = contact.MobilePhone.ToString(); 34 txtAge.Text = contact.Age.ToString(); 35 36 clearInputControls(); 37 } 38 39 private void btnClear_Click(object sender, System.EventArgs e) 40 { 41 clearInputControls(); 42 } 43 44 private void btnClose_Click(object sender, System.EventArgs e) 45 { 46 Close(); 47 } 48 49 private void btnDelete_Click(object sender, System.EventArgs e) 50 { 51 clsContact contact; 52 53 // Make sure an item is selected in the listbox. 54 55 if (lstContacts.SelectedItem == null) 56 { 57 return; 58 }

Page 19: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-19

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

59 60 contact = (clsContact)lstContacts.SelectedItem; 61 62 // Ask the user for confirmation. 63 64 if (messageBoxYesNo("Are you sure you want to delete " 65 + contact.LastFirstName + "?") == DialogResult.No) 66 { 67 return; 68 } 69 70 // Remove the contact from the listbox. 71 72 lstContacts.Items.Remove(lstContacts.SelectedItem); 73 } 74 75 private void btnUpdate_Click(object sender, System.EventArgs e) 76 { 77 clsContact contact; 78 79 // Make sure an item is selected in the listbox. 80 81 if (lstContacts.SelectedItem == null) 82 { 83 return; 84 } 85 86 if (validateInput() == false) 87 { 88 return; 89 } 90 91 // Populate the existing contact item with the new values. 92 93 contact = (clsContact)lstContacts.SelectedItem; 94 getInputValues(contact); 95 96 lstContacts.Items.Remove(contact); 97 lstContacts.Items.Add(contact); 98 clearInputControls(); 99 } 100 101 // Displays the property values for the selected contact values. 102 103 private void lstContacts_DoubleClick(object sender, System.EventArgs e) 104 { 105 // Make sure an item is selected in the listbox. 106 107 if (lstContacts.SelectedItem == null) 108 { 109 return; 110 } 111 112 // Get the reference to the selected contact. 113 114 clsContact contact = (clsContact)lstContacts.SelectedItem; 115 116 // Display the contact's property values. 117 118 txtFirstName.Text = contact.FirstName; 119 txtLastName.Text = contact.LastName; 120 txtHomePhone.Text = contact.HomePhone.ToString(); 121 txtMobilePhone.Text = contact.MobilePhone.ToString(); 122 txtBirthDate.Text = contact.BirthDate.ToString("d"); 123 txtAge.Text = contact.Age.ToString(); 124 } 125 126 private void clearInputControls() 127 { 128 txtFirstName.Text = ""; 129 txtLastName.Text = "";

Page 20: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-20 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

130 txtHomePhone.Text = ""; 131 txtMobilePhone.Text = ""; 132 txtBirthDate.Text = ""; 133 txtAge.Text = ""; 134 txtFirstName.Focus(); 135 } 136 137 private void getInputValues(clsContact contact) 138 { 139 contact.FirstName = txtFirstName.Text; 140 contact.LastName = txtLastName.Text; 141 contact.HomePhone = new clsPhoneNumber(txtHomePhone.Text,1); 142 contact.MobilePhone = new clsPhoneNumber(txtMobilePhone.Text); 143 contact.BirthDate = DateTime.Parse(txtBirthDate.Text); 144 } 145 146 private void messageBoxOK(string msg) 147 { 148 MessageBox.Show(msg, Text, 149 MessageBoxButtons.OK, MessageBoxIcon.Information); 150 } 151 152 private DialogResult messageBoxYesNo(string msg) 153 { 154 return MessageBox.Show(msg, Text, 155 MessageBoxButtons.YesNo, MessageBoxIcon.Question); 156 } 157 158 private bool validateInput() 159 { 160 DateTime birthDate; 161 162 if (txtFirstName.Text == "") 163 { 164 messageBoxOK("First Name is required."); 165 txtFirstName.Focus(); 166 return false; 167 } 168 169 if (txtLastName.Text == "") 170 { 171 messageBoxOK("Last Name is required."); 172 txtLastName.Focus(); 173 return false; 174 } 175 176 if (DateTime.TryParse(txtBirthDate.Text, out birthDate) == false) 177 { 178 messageBoxOK("Birthdate is required and must be a valid date."); 179 txtBirthDate.Focus(); 180 return false; 181 } 182 183 clsPhoneNumber phone = new clsPhoneNumber(txtHomePhone.Text, 1); 184 185 // If we get here, then everything must be OK. 186 return true; 187 } 188 }

Figure 10-18 Complete source code for the frmMain class 1 using System; 2 3 public class clsContact 4 { 5 private string mFirstName; 6 private string mLastName; 7 public clsPhoneNumber HomePhone; 8 public clsPhoneNumber MobilePhone;

Page 21: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-21

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

9 public DateTime BirthDate; 10 11 public clsContact() 12 { 13 mFirstName = ""; 14 mLastName = ""; 15 HomePhone = new clsPhoneNumber(""); 16 MobilePhone = new clsPhoneNumber(""); 17 BirthDate = DateTime.MinValue; 18 } 19 20 public clsContact(string first, string last) 21 { 22 mFirstName = first; 23 mLastName = last; 24 HomePhone = new clsPhoneNumber(""); 25 MobilePhone = new clsPhoneNumber(""); 26 BirthDate = DateTime.MinValue; 27 } 28 29 public string FirstName 30 { 31 get 32 { 33 return mFirstName; 34 } 35 36 set 37 { 38 string temp; 39 40 value = value.ToLower(); 41 temp = value.Substring(0, 1); 42 value = temp.ToUpper() + 43 value.Substring(1, value.Length - 1); 44 45 mFirstName = value; 46 } 47 } 48 49 public string LastName 50 { 51 get 52 { 53 return mLastName; 54 } 55 56 set 57 { 58 string temp; 59 60 value = value.ToLower(); 61 temp = value.Substring(0,1); 62 value = temp.ToUpper() + 63 value.Substring(1,value.Length - 1); 64 65 mLastName = value; 66 } 67 } 68 69 public string LastFirstName 70 { 71 get 72 { 73 return mLastName + ", " + mFirstName; 74 } 75 } 76 77 public byte Age 78 { 79 get

Page 22: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-22 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

80 { 81 // Get the birth date value for the current year. 82 83 DateTime thisYearBirthDate = 84 new DateTime(DateTime.Now.Year, BirthDate.Month, BirthDate.Day); 85 86 // Calculate and return the age based on if 87 // the birth date has occurred this year or not. 88 89 if (thisYearBirthDate <= DateTime.Now) 90 { 91 return (byte)(DateTime.Now.Year - BirthDate.Year); 92 } 93 else 94 { 95 return (byte)(DateTime.Now.Year - BirthDate.Year - 1); 96 } 97 } 98 } 99 } 100

Figure 10-19 Complete source code for the clsContact class 1 using System; 2 3 public class clsPhoneNumber 4 { 5 private string mPhoneNumber = ""; 6 7 // Default values for USA. USA = 1, Europe = 2 8 9 private int mWhichCountry = 1; 10 11 // USA = '-', Europe = '.' 12 13 private char mSpacer = '-'; 14 15 // The ToString method is overridden 16 // to return the formatted phone number. 17 18 public override string ToString() 19 { 20 return mPhoneNumber; 21 } 22 23 // This constructor takes a string value as the argument, and 24 // removes any character that isn't one of the numbers 0 - 9, 25 // then saves it formatted as (999) 999-9999. An exception is 26 // thrown if the string contains more than 10 numeric characters. 27 28 public clsPhoneNumber(string value) 29 { 30 // Skip the reformatting if all we have is an empty string. 31 32 string temp; 33 34 if (value == "") 35 { 36 mPhoneNumber = ""; 37 return; 38 } 39 40 temp = checkString(value); 41 formatmPhoneNumber(temp); 42 } 43 44 // This constructor uses a second parameter to decide the 45 // country-specific formatting to use. 46

Page 23: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-23

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

47 public clsPhoneNumber(string value, int which) 48 { 49 // Skip the reformatting if all we have is an empty string. 50 51 string temp; 52 53 mWhichCountry = which; 54 55 if (value == "") 56 { 57 mPhoneNumber = ""; 58 return; 59 } 60 61 // Change the character between digits based on locale. 62 63 switch (mWhichCountry) 64 { 65 // USA. 66 67 case 1: 68 mSpacer = '-'; 69 break; 70 71 // Europe. 72 73 case 2: 74 mSpacer = '.'; 75 break; 76 77 // Default assumes USA. 78 79 default: 80 mSpacer = '-'; 81 break; 82 } 83 temp = checkString(value); 84 formatmPhoneNumber(temp); 85 } 86 87 //Format the phone number based upon its length, which 88 //may or may not include an area code. 89 90 private void formatmPhoneNumber(string digits) 91 { 92 switch (digits.Length) 93 { 94 //Default for no area code. 95 96 case 7: 97 mPhoneNumber = digits.Substring(0, 3) 98 + mSpacer + digits.Substring(3, 4); 99 break; 100 101 // Format with area code. 102 103 case 10: 104 mPhoneNumber = "(" 105 + digits.Substring(0, 3) 106 + ") " 107 + digits.Substring(3, 3) 108 + mSpacer 109 + digits.Substring(6, 4); 110 break; 111 112 default: 113 throw new Exception("Improper number of numeric digits."); 114 } 115 } 116 117 private string checkString(string value)

Page 24: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-24 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

118 { 119 // Remove any character that isn't a digit character 0 - 9. 120 121 char digit; 122 string digits = ""; 123 124 for (int index = 0; index < value.Length; index++) 125 { 126 digit = value[index]; 127 if (digit >= '0' && digit <= '9') 128 { 129 digits += digit; 130 } 131 } 132 return digits; 133 } 134 }

Figure 10-20 Complete source code for the clsPhoneNumber class

Page 25: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-25

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

BONUS TOPICS MEMORY MANAGEMENT

Memory is often the primary computer resource used by an application. As such, proper management of memory is essential so that your applications do not waste limited memory resources, run slowly, or worst of all – crash. Fortunately for C# developers, the .NET framework handles most memory management tasks automatically. An understanding of these memory management processes, however, can assist developers in writing more efficient code.

Two sections of memory are of particular relevance during application execution – the program stack and the managed heap. The program stack and the managed heap differ significantly, as we will discuss below. However, it is from these two sections of memory that resources required by an executing program are drawn.

The Program Stack The program stack is a finite section of memory used during program execution. Items added to the stack are always assigned to the top of the stack. While they occupy the top of the stack, they are the only items accessible from the entire stack. Once the items are no longer needed, they are removed from the stack entirely. Only then are the items directly underneath again accessible.

A common analogy used to describe the program stack is that of storage boxes “stacked” one on top of another. The amount of space required to store things in this manner is relatively small. However, only the contents of the uppermost box are accessible to you. Also, when you need to store a new box, it has to be placed on the very top of the stack – thus further restricting access to the contents of any box located lower in the stack. When you are done with the uppermost box, it and all of its contents are thrown away – they are literally gone, and can never again be accessed. However, upon discarding the uppermost box the one immediately below it now becomes accessible.

Memory in the program stack is used to store:

Local scope value types Local scope object references

You should be very familiar with value types, both local and class scope, at this point. Object references were discussed in Chapter 5 – if you do not recall what an object reference is, you may wish to review that material before proceeding.

The memory allocation and reclamation mechanism used by the program stack is referred to as last in, first out (LIFO). This is because the items placed upon the top of the stack are always the last ones introduced. These same items will also be the first ones removed. The LIFO mechanism provides the program stack with an efficient means of memory allocation and reclamation, allowing it to be self-managing with regards to memory.

The Managed Heap The common language runtime (CLR) implicitly manages memory located in the heap. This is referred to as automatic memory management, and is only one of many functions performed by the CLR.

Page 26: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-26 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

A common analogy used to describe the managed heap is that of storage boxes laid out singly upon the floor. The contents of any box can be accessed at any given time. However, keeping storage boxes laid out on the floor requires much more space than stacking them.

Memory in the managed heap is used to store reference-type objects and the value of any of there class-scope variables.

Unlike the program stack, all data stored in the managed heap is accessible at all times. However, accessing the managed heap is typically slower than accessing the program stack. Because of this, local variable usage (i.e., variables that are stored in stack memory) produces better performing applications.

Garbage Collection The specific component of the CLR responsible for the allocation and deallocation of memory is known as the garbage collector. The garbage collector periodically traces references to all objects in the managed heap. Any object found without at least one reference from running code is deallocated, and the memory it consumes released to the managed heap.

In many programming languages, developers are responsible for explicitly deallocating objects from memory once the object is no longer of use. If developers using these languages fail to remove objects after they are no longer of use, the resources those objects consume are never released. As these programs run, the amount of memory consumed continually increases until eventually no available memory is left, causing the program to crash. When this happens, it is said the program is “leaking memory” or has a “memory leak”.

Additionally problematic is if developers using programming languages without automatic memory management release an object from memory, and a different part of the program attempts to use that object, a null reference exception might occur, data might become corrupted, or the program may crash.

In C#, object references are automatically deallocated by the garbage collector as they go out of scope. This is true whether the object reference is stored in the program stack (i.e., a local scope object reference), or between multiple objects stored in the managed heap (e.g., one object referencing another object).

Once all references to an object have been deallocated, the object is said to be unreferenced. As noted previously, unreferenced objects are targeted for garbage collection, which ultimately deallocates the memory consumed by the object.

STATIC CLASSES So far we have discussed only classes that need to be instantiated prior to their use. For example, the clsContact class we have been using throughout the chapter. Prior to accessing any its class members, an object instance of the class needs to be created.

This is not the case with static classes, however. Static classes do not require instantiation prior to usage. In fact, if you attempt to instantiate a static class, you will get a compiler error.

In addition to this difference, static classes differ from non-static classes in that they may contain only static class members. This makes sense because static classes cannot be instantiated. Without instantiation, there is no object. And without an object, there is no object state for the class member to use (recall from the Bonus section of Chapter 7 that methods that do not use object state as they perform their task are well suited to be static).

Page 27: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-27

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Static Methods

Static methods were discussed in the Bonus section of Chapter 7. If you have not already read it, you should do so now. The remainder of Chapter 10 presumes that you already possess an understanding of this topic.

Uses for Static Classes Static classes commonly serve as containers for methods and constants that would not vary between object instances. This means a static class is an ideal places to put general-purpose helper methods that will be used throughout a program, and that will likely be reused in other programs as well.

Take for example PI. Its value is always the same, and it does not rely upon the specific state of any class. Because of this, C# houses the value of PI in a static container dedicated to mathematical constants and methods, the System.Math class. The Math class is one of the commonly used static classes in C#, and one with which you are probably already familiar.

Accessing members of a static class is similar to accessing members of a non-static class. It is done via the familiar dot notation. However, because you do not instantiate a static class, you do not prefix the member name with the instance name. Instead, you prefix the member name with the class name. For example, Math.PI is how you access the value of PI, as shown on line 3 in Figure 10-21.

1 public static double GetCircumference(double radius) 2 { 3 double circumference = 2 * Math.PI * radius; 4 return circumference; 5 }

Figure 10-21 Using a Static Member (Math.PI)

Creating a Static Class In code, class members are made static via use of the static keyword applied immediately after the access specifier (i.e., public, private) and before the keyword class. Creation of a static class named clsUnitConversions is illustrated in Figure 10-22.

1 using System; 2 3 public static class clsUnitConversions 4 { 5 6 }

Figure 10-22 Creation of a Static Class

Page 28: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-28 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

Creating Static Class Members As previously discussed, static classes can contain only static class members. If you try to compile a static class that contains a non-static member, you will get an error.

In code, class members are made static via use of the static keyword. The static keyword is applied immediately prior to the data type in the case of variables and properties, and immediately prior to return type in the case of methods. Creation of a static “read-only” property is illustrated in Figure 10-23, while creation of a static method is illustrated in Figure 10-24.

5 public static double LitersPerGallon 6 { 7 get 8 { 9 return 3.7854118; 10 } 11 }

Figure 10-23 Creation of a Static Property

13 public static double LitersToGallons(double numberOfLiters) 14 { 15 double numberOfGallons; 16 numberOfGallons = numberOfLiters / LitersPerGallon; 17 18 return numberOfGallons; 19 }

Figure 10-24 Creation of a Static Method

Notice that the LitersToGallons method accepts an argument. This demonstrates that static methods can – and typically are – parameterized. Also notice that the LitersToGallons method uses the LitersPerGallon property. This demonstrates that static class members can access each other.

One warning: constants cannot be declared static. Because of this, static classes cannot incorporate constant class members. However, read-only properties often serve the same purpose as constants, and may often be used in place of them in static classes.

A Complete Static Class Figure 10-25 contains complete source code for the clsUnitConversions static class.

1 using System; 2 3 public static class clsUnitConversions 4 { 5 public static double LitersPerGallon 6 { 7 get

Page 29: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-29

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

8 { 9 return 3.7854118; 10 } 11 } 12 13 public static double LitersToGallons(double numberOfLiters) 14 { 15 double numberOfGallons; 16 numberOfGallons = numberOfLiters / L3itersPerGallon; 17 18 return numberOfGallons; 19 } 20 21 public static double GallonsToLiters(double numberOfGallons) 22 { 23 double numberOfLiters; 24 numberOfLiters = numberOfGallons * LitersPerGallon; 25 26 return numberOfLiters; 27 } 28 }

Figure 10-25 Source code for the clsUnitConversions static class Notice that it contains two public parameterized static methods, as well as a public read-only property. Recall that any of these three public class members can be access from anywhere in the program using the standard dot notation. Usage of the LitersToGallons method from a button click event is demonstrated on line 29 of Figure 10-26.

4 public partial class frmMain : Form 5 { 17 private void btnCalculate_Click(object sender, EventArgs e) 18 { 19 double numberLiters; 20 double numberGallons; 21 22 if (double.TryParse(txtLiters.Text, out numberLiters) == false) 23 { 24 messageBoxShow("Number of Liters must be a valid number."); 25 txtLiters.Focus(); 26 return; 27 } 28 29 numberGallons = clsUnitConversions.LitersToGallons(numberLiters); 30 txtGallons.Text = numberGallons.ToString(); 31 } 38 }

Figure 10-26 Accessing the Members of a Static Class from frmMain

Page 30: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-30 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

SUMMARY Essential Topics

Encapsulation is one of the cornerstone design principles of object-oriented programming. It promotes the creation of self-contained code modules, directly resulting in increased control of an object’s state. Encapsulation ultimately results in code that is easier to reuse, test, debug, deploy, and support.

The primary means of creating encapsulated code in object-oriented programming is through use of the class. The term class member refers to those class scope variables, properties, and methods that are used to manage the state of individual objects instantiated from that class.

An object is an individual instance of a class. The process of creating a new object based upon a class definition is referred to as instantiation. The state of an instantiated object is defined by the values held in its members.

Accessibility modifiers define which elements in a program can access class members. The two most commonly used accessibility modifier are public and private. Public accessibility allows all elements within the program to access the data member, while private accessibility limits access only to logic residing in the same class as the data member. If accessibility is not explicitly specified in the definition of a data member, it defaults to private.

The interface of a class is defined by those class members that are publically accessible to other elements within the program. Private class members are not accessible from outside the class, and are thus not a part of a class’s interface.

Class properties can be used to provide highly controlled, indirect access to an object’s state. Each property consists of a property name, and at least one accessor method. The get accessor method is typically used to provide indirect reading of an objects state. The set accessor method implicitly accepts a parameter, and is typically used to modify an object’s state. A property that has only a get accessor method is “read only”, while a property that has only a set accessor method is “write only”. A property that has both get and set accessor methods is “read-write”. Properties defined as publically accessible are a part of a class’s interface.

The initial state of an object is defined by the initial value assigned to its data members. These values can be explicitly set by providing an initial value in the data member’s definition, a process referred to as initialization. Alternately, the initial value of data members can be explicitly set via use of class constructors. Any data member which is not explicitly assigned a value has one implicitly assigned by the CLR at runtime, the value of which is based upon the member’s data type.

Class constructors share the same name as the class itself. All classes have at least one constructor: the default class constructor. The default class constructor has no parameters. If a default class constructor is not explicitly defined in the class definition (i.e., by the developer), then the C# compiler implicitly creates on for the class.

Class constructors can be both parameterized and overloaded. Parameterized class constructors are often used to dynamically set the state of an object at runtime. The practice of overloading class constructors allows developers a great deal of flexibility in designing the interface of a class.

Page 31: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-31

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

Bonus Topics Applications on the .NET platform (including C#) do not require explicit memory

management. Instead, memory reclamation occurs implicitly as items go out of scope.

Local scope value types and object pointers use memory stored in the program stack. Stack resources are allocated in a “last in, first out” (LIFO) manner, and as such are largely self-regulating.

Reference types use memory stored in the managed heap. When an object in the heap is no longer referenced, the memory it is consuming is reclaimed via garbage collection processes handled by the .NET platform’s common language runtime (CLR).

Static classes are similar to non-static classes, but are not instantiated. They serve as ideal containers for general-purpose methods that are needed throughout an entire program, regardless of the state of any specific object. Static classes can contain only static class members, which are accessed using the standard dot notation. However, in place of an instance name, the name of the static class is used.

KEY TERMS Define each of the following terms, as it relates to encapsulation.

Essential Terms Class Constructor Class Declaration Class Instantiation Class Interface Class Property Class Member Data Member Encapsulation Get Accessor Initialization Public Access Specifier Private Access Specifier

Set Accessor

Bonus Terms Garbage Collector

LIFO

Managed Heap Unreferenced Object Program Stack Static class Static class member

Page 32: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-32 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

REVIEW QUESTIONS Essential Questions

1. Encapsulation is a concept unique to object-oriented programming. True or false? 2. One goal of encapsulation is to de-modularize application code. True or false? 3. What does a black box have to do with encapsulation? 4. What are the primary means used in object-oriented programming to implement encapsulation? 5. What are the two most commonly used access specifiers? 6. The ____________ access specifier is the default access specifier. 7. ______________ can be used to provide highly controlled, indirect access to an object’s private

data members. 8. If a property is located on the left side of an assignment operation, the ____________ accessor

method will be called. 9. The ____________ accessor method possesses an implicit parameter. 10. A read-only property has the ____________ accessor method but lacks the ____________

accessor method. 11. A write-only property has the ____________ accessor method but lacks the ____________

accessor method. 12. All data members possess a value at all times. True or false? 13. Data members declared as constant must be initialized at declaration. True or false? 14. If a value is not explicitly assigned to a data member, what determines its value? 15. Every class has at least one constructor. What is it? 16. Class constructors can be overloaded. True or false? 17. In general, class constructors can be parameterized. True or false? 18. The default class constructor can be parameterized. True or false? 19. What are some common uses for explicit constructors?

Bonus Questions 1. Resources allocated to local scope value types are located in the ____________ ____________. 2. Resources allocated to reference types are located in the ____________ ____________. 3. How are object references freed? 4. The program stack uses a LIFO method of managing resources. True or false? 5. LIFO stands for: ____________ ____________, ____________ ____________. 6. The garbage collector is responsible for the reclaiming of resources held by unreferenced

objects. True or false? 7. The garbage collector reclaims resources found in the program stack. True or false? 8. A static class must be instantiated prior to use. True or false? 9. Which class member types can be declared static?

Page 33: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

Chapter 10 – Encapsulation 10-33

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com

copyright © 2011 Kyle Lutes & Alka Harriger

PROGRAMMING EXERCISES Each of the following exercises will require you to create not only a new class, but a means to test this new class. The easiest means to do so is to create a small program that uses the newly created class.

Essential Exercises 1. Take any programming exercise presented in a previous chapter, and break it into its own fully

encapsulated class. Be sure to name all classes as per our naming standards, and specify access to all class members as appropriate.

2. Alter the Contact List program created in Chapter 10 to also include the email addresses belonging to each contact. Realize that like a telephone number, each contact can have 0, 1, or multiple email addresses (e.g., personal, work, school, etc.) which should be displayed in a listbox. The specific email address information should be retained in a class named clsEmailAddress. Accept the implicit default constructor for this class, and make retain the object’s state as public data members.

3. Alter the interface of the email address class created above. Make the data members private and allow only indirect access to the class’s state via properties. Use the class property set accessors to apply a standard format prior to setting any state values. Specifically, the email type and email address values provided should be formatted to lowercase (e.g., school, [email protected]) prior to assignment of object state.

4. Further alter the interface of the email address class created above. While retaining the implicit default constructor, create a new parameterized constructor as well. This new constructor should accept 2 values: email type, and email address. These values should be appropriately formatted (i.e., converted to lowercase) prior to assignment of object state.

Bonus Exercises 1. Create a static class named clsUnitConversions to enable translation of US and

European units of distance. The class should have the following methods:

a) A method to convert miles to kilometers.

b) A method to convert kilometers to miles.

c) A method to convert feet to meters.

d) A method to convert meters to feet.

2. Enhance the clsUnitConversions class to enable translation of commonly used units of temperature. The class should have the following methods:

a) A method to convert Fahrenheit to Celsius.

b) A method to convert Celsius to Fahrenheit.

c) A method to convert Celsius to Kelvin.

d) A method to convert Kelvin to Celsius.

Page 34: CHAPTER 10 ENCAPSULATION - oopusingcsharp.comoopusingcsharp.com/Chapter10Sample.pdf · Encapsulation is one of the cornerstone design principles of object-oriented programming. The

10-34 Chapter 10 – Encapsulation

An Information Systems Approach to Object-Oriented Programming using Microsoft Visual C# Express www.OOPUsingCSharp.com copyright © 2011 Kyle Lutes & Alka Harriger

This page is intentionally left blank