Account
Class with an Instance Variable and Set and Get MethodsThe fact that in Fig. 4.1 we could create and manipulate an Account
object without knowing its implementation details is called abstraction. This is one of the most powerful software-engineering benefits of object-oriented programming. Now that we’ve seen class Account
in action (Fig. 4.1), in the next several sections we’ll explain its implementation in detail. Then, we present a UML diagram that summarizes class Account
’s attributes and operations in a concise graphical representation.
Account
Class DeclarationClass Account
(Fig. 4.2) contains a name
instance variable (line 7) that stores the account holder’s name—each Account
object has its own copy of the name
instance variable. In Section 4.9, we’ll add a balance
instance variable to keep track of the current balance in each Account
. Class Account
also contains method SetName
that a program can call to store a name in an Account
object, and method GetName
that a program can call to obtain the name from an Account
object.
class
and the Class BodyThe class declaration begins in line 5 with
class Account
As we mentioned in Chapter 3, every class declaration contains the keyword class
followed immediately by the class’s name—in this case, Account
. Also, each class declaration is typically stored in a file having the same name as the class and ending with the .cs
filename extension, so we’ve placed class Account
in the file Account.cs
. The class’s body is enclosed in a pair of braces (lines 6 and 20 of Fig. 4.2).
Class, property, method and variable names are all identifiers and by convention all use the naming schemes we discussed in Chapter 3:
class, property and method names begin with an initial uppercase letter (i.e., Pascal case)
variable names begin with an initial lowercase letter (i.e., camel case).
name
of Type string
Recall from Section 1.6 that a class has attributes, implemented as instance variables. Objects of the class carry these instance variables with them throughout their lifetimes. Each object has its own copy of the class’s instance variables. Normally, a class also contains methods and properties. These manipulate the instance variables belonging to particular objects of the class.
Instance variables are declared inside a class declaration but outside the bodies of the class’s methods and properties. Line 7
private string name; // instance variable
declares instance variable name
of type string
outside the bodies of methods SetName
and GetName
. If there are many Account
objects, each has its own name
. Because name
is an instance variable, it can be manipulated by each of the class’s methods and properties. Clients of class Account
—that is, any other code that calls the class’s methods (such as class AccountTest
’s Main
method in Fig. 4.1)—cannot access the name
instance variable because it’s declared private
. However, clients can access Account
’s public
methods Set-Name
and GetName
. These methods can access private
instance variable name
. We discuss private
and public
in Section 4.3.6, then discuss why this architecture of private
instance variables and public
access methods is powerful in more detail in Section 4.5.
We prefer to list a class’s instance variables first in the class’s body, so that you see the names and types of the variables before they’re used in the class’s methods and properties. You can list the class’s instance variables anywhere in the class outside its method (and property) declarations, but scattering the instance variables can lead to hard-to-read code.
null
—the Default Initial Value for string
VariablesEvery instance variable has a default initial value—a value provided by C# if you do not specify the instance variable’s initial value. Thus, instance variables are not required to be explicitly initialized before they’re used in a program—unless they must be initialized to values other than their default values. The default value for an instance variable of type string
(like name
in this example) is null
, which we discuss further in Chapter 7 when we consider so-called reference types. When you use Console.Write
or Console.WriteLine
to display a string
variable that contains the value null
, no text is displayed on the screen—this is why line 13 in Main
(Fig. 4.1) did not display a name the first time we called myAccount
’s GetName
method.
SetName
MethodLet’s walk through the code of method SetName
’s declaration (Fig. 4.2, lines 10–13):
public void SetName(string accountName)
{
name = accountName; // store the account name
}
The first line of each method declaration (line 10) is the method header. The method’s return type (which appears to the left of the method’s name) specifies the type of data the method returns to its caller after performing its task. The return type void
(line 10) indicates that when SetName
completes its task, it does not return (i.e., give back) any information to its calling method—in this example, line 18 of the Main
method (Fig. 4.1). As you’ll soon see, Account
method GetName
does return a value.
SetName
’s ParameterOur car analogy from Section 1.6 mentioned that pressing a car’s gas pedal sends a message to the car to perform a task—make the car go faster. But how fast should the car accelerate? The farther down you press the pedal, the faster the car accelerates. So the message to the car includes both the task to perform and information that helps the car perform that task. This information is known as a parameter—the parameter’s value helps the car determine how fast to accelerate. Similarly, a method can require one or more parameters that represent the data it needs to perform its task.
Method SetName
declares the string
parameter accountName
—which receives the name that’s passed to SetName
as an argument. When line 18 in Fig. 4.1
myAccount.SetName(theName); // put theName in the myAccount object
executes, the argument value in the call’s parentheses (i.e., the value stored in theName
) is copied into the corresponding parameter (accountName
) in the method’s header (line 10 of Fig. 4.2). In Fig. 4.1’s sample execution, we entered "Jane Green"
for theName
, so "Jane Green"
was copied into the accountName
parameter.
SetName
Parameter ListParameters like accountName
are declared in a parameter list located in the required parentheses following the method’s name. Each parameter must specify a type (e.g., string
) followed by a parameter name (e.g., accountName
). When there are multiple parameters, they are placed in a comma-separated list, as in
(type1 name1, type2 name2, …)
The number and order of arguments in a method call must match the number and order of parameters in the method declaration’s parameter list.
SetName
Method BodyEvery method body is delimited by an opening left brace (Fig. 4.2, line 11) and a closing right brace (line 13). Within the braces are one or more statements that perform the method’s task(s). In this case, the method body contains a single statement (line 12)
name = accountName; // store the account name
that assigns the accountName
parameter’s value (a string
) to the class’s name
instance variable, thus storing the account name in the object for which SetName
was called—myAccount
in this example’s Main
program.2 After line 12 executes, program execution reaches the method’s closing brace (line 13), so the method returns to its caller.
In Chapter 3, we declared all of an app’s variables in the Main
method. Variables declared in a particular method’s body (such as Main
) are local variables which can be used only in that method. Each method can access only its own local variables, not those of other methods. When a method terminates, the values of its local variables are lost. A method’s parameters also are local variables of the method.
GetName
MethodMethod GetName
(lines 16–19)
public string GetName()
{
return name; // returns name's value to this method's caller
}
returns a particular Account
object’s name
to the caller—a string
, as specified by the method’s return type. The method has an empty parameter list, so it does not require additional information to perform its task. When a method with a return type other than void
is called and completes its task, it must return a result to its caller. A statement that calls method GetName
on an Account
object expects to receive the Account
’s name.
The return
statement in line 18
return name; // returns name's value to this method's caller
passes the string
value of instance variable name
back to the caller, which can then use the returned value. For example, the statement in line 21 of Fig. 4.1
Console.WriteLine($"myAccount's name is: {myAccount.GetName()}");
uses the value returned by GetName
to output the name stored in the myAccount
object.
private
and public
The keyword private
(line 7 of Fig. 4.2)
private string name; // instance variable
is an access modifier. Instance variable name
is private
to indicate that name
is accessible only to class Account
’s methods (and other members, like properties, as you’ll see in subsequent examples). This is known as information hiding—the instance variable name
is hidden and can be used only in class Account
’s methods (SetName
and GetName
). Most instance variables are declared private
.
This class also contains the public
access modifier (line 10)
public void SetName(string accountName)
and line 16
public string GetName()
Methods (and other class members) that are declared public
are “available to the public.” They can be used
by methods (and other members) of the class in which they’re declared,
by the class’s clients—that is, methods (and other members) of any other classes (in this app, class AccountTest
’s Main
method is the client of class Account
).
In Chapter 11, we’ll introduce the protected
access modifier.
By default, everything in a class is private
, unless you specify otherwise by providing access modifiers.
Making a class’s instance variables private
and its methods (and as you’ll see, properties) public and accessing those instance variables only through the class’s methods and properties facilitates debugging, because problems with data manipulations are localized to the methods (and properties).
An attempt by a method that’s not a member of a particular class to access a private
member of that class is a compilation error.
Account
UML Class DiagramWe’ll often use UML class diagrams to summarize a class’s attributes and operations. In industry, UML diagrams help systems designers specify systems in a concise, graphical, programming-language-independent manner, before programmers implement the systems in specific programming languages. Figure 4.3 presents a UML class diagram for class Account
of Fig. 4.2.
In the UML, each class is modeled in a class diagram as a rectangle with three compartments. In this diagram the top compartment contains the class name Account
centered horizontally in boldface type.
The middle compartment contains the class’s attribute names, which correspond to the instance variables of the same names in C#. The single instance variable name
in Fig. 4.2 is private
in C#, so the UML class diagram lists a minus sign (–
) UML access modifier be-fore the attribute’s name. Following the attribute’s name are a colon and the attribute type, in this case string
.
The bottom compartment contains the class’s operations, SetName
and GetName
, which correspond to the methods of the same names in C#. The UML models operations by listing the operation name preceded by a UML access modifier, for example, + SetName
. This plus sign (+
) indicates that SetName
is a public operation in the UML (because it’s a public
method in C#). Operation GetName
is also a public operation.
The UML indicates an operation’s return type by placing a colon and the return type after the parentheses following the operation name. Method SetName
does not return a value (because it returns void
in C#), so the UML class diagram does not specify a return type after the parentheses of this operation. Method GetName
has a string
return type. The UML has its own data types similar to those of C#—for simplicity, we use the C# types.
The UML models a parameter by listing the parameter name, followed by a colon and the parameter type in the parentheses after the operation name. Account
method SetName
has a string
parameter called accountName
, so the class diagram lists
accountName : string
between the parentheses following the method name. Operation GetName
does not have any parameters, so the parentheses following the operation name in the class diagram are empty, just as they are in the method’s declaration in line 16 of Fig. 4.2.