Account
Class: Initializing Objects with ConstructorsAs mentioned in Section 4.6, when an object of class Account
(Fig. 4.6) is created, its string
instance variable name
is initialized to null
by default. But what if you want to provide an actual name when you create an Account
object?
Each class you declare optionally can provide a constructor with parameters that can be used to initialize an object when it’s created. C# requires a constructor call for every object that’s created, so this is the ideal point to initialize an object’s instance variables. The next example enhances class Account
(Fig. 4.8) with a constructor that can receive a name and use it to initialize the Name
property when an Account
object is created (Fig. 4.9). Now that you’ve seen class Account
in action, this chapter’s two remaining examples present class Account
before class AccountTest
.
This version of class Account
replaces the private name
instance variable and the public Name
property from Fig. 4.6 with a public
auto-implemented Name
property (Fig. 4.8, line 6). This property automatically creates a hidden private
instance variable to store the property’s value.
Account
Constructor for Custom Object InitializationWhen you declare a class, you can provide your own constructor to specify custom initialization for objects of your class. For example, you might want to specify a name for an Account
object when the object is created, as in line 11 of Fig. 4.9:
Account account1 = new Account("Jane Green");
In this case, the string
argument "Jane Green"
is passed to the Account
object’s constructor and used to initialize the Account
’s name. A constructor’s identifier must be the class’s name. The preceding statement requires an Account
constructor that can receive a string
. Figure 4.8 contains a modified Account
class with such a constructor.
Account
Constructor DeclarationLet’s walk through the code of the constructor’s declaration (Fig. 4.8, lines 9–12):
public Account(string accountName) // constructor name is class name
{
Name = accountName;
}
We refer to the first line of each constructor declaration (line 9 in this case) as the constructor header. This constructor receives the string
parameter accountName
—which represents the name that’s passed to the constructor as an argument. An important difference between constructors and methods is that constructors cannot specify a return type (not even void
). Normally, constructors are declared public
so they can be used by the class’s client code to initialize objects of the class.
A constructor’s body is delimited by a pair of braces (lines 10 and 12 of Fig. 4.8) containing one or more statements that perform the constructor’s task(s). In this case, the body contains one statement (line 11) that assigns parameter accountName
’s value (a string
) to the class’s Name
property, thus storing the account name in the object. After line 11 executes, the constructor has completed its task, so it returns to the line of code containing the object-creation expression that invoked the constructor. As you’ll soon see, the statements in lines 11–12 of Main
(Fig. 4.9) each call this constructor.
AccountTest
: Initializing Account
Objects When They’re CreatedThe AccountTest
program (Fig. 4.9) initializes two Account
objects using the constructor. Line 11 creates and initializes the Account
object account1
. Keyword new
requests memory from the system to store the Account
object, then implicitly calls the class’s constructor to initialize the object. The call is indicated by the parentheses after the class name, which contain the argument "Jane Green"
that’s used to initialize the new object’s name. Line 11 then assigns the initialized object to the variable account1
. Line 12 repeats this process, passing the argument "John Blue"
to initialize the name for account2
. Lines 15–16 use each object’s Name
property to obtain the names and show that they were indeed initialized when the objects were created. The output shows different names, confirming that each Account
maintains its own name.
Recall that line 10 of Fig. 4.5
Account myAccount = new Account();
used new
to create an Account
object. The empty parentheses in the expression
new Account()
indicate a call to the class’s default constructor—in any class that does not explicitly declare a constructor, the compiler provides a public
default constructor (which always has no parameters). When a class has only the default constructor, the class’s instance variables are initialized to their default values:
0 for numeric simple types,
false
for simple type bool
and
null
for all other types.
In Section 10.5, you’ll learn that classes can have multiple constructors through a process called overloading.
If you declare one or more constructors for a class, the compiler will not create a default constructor for that class. In that case, you will not be able to create an Account
object with the expression new Account()
as we did in Fig. 4.5—unless one of the custom constructors you declare takes no parameters.
Unless default initialization of your class’s instance variables is acceptable, provide a custom constructor to ensure that your instance variables are properly initialized with meaningful values when each new object of your class is created.
Account
’s UML Class DiagramThe UML class diagram of Fig. 4.10 models class Account
of Fig. 4.8, which has a constructor with a string accountName
parameter. The UML models constructors as operations in the third compartment of a class diagram. To distinguish a constructor from the class’s other operations, the UML requires that the word “constructor” be enclosed in guillemets (« and ») and placed before the constructor’s name. It’s customary to list constructors before other operations in the third compartment. In Fig. 4.14, you’ll see a class diagram with both a constructor and an operation in the third compartment.