|
|
Module 9: Creating and Destroying Objects 13
u Initializing Data
n Using Initializer Lists
n Declaring Readonly Variables and Constants
n Initializing Readonly Fields
n Declaring a Constructor for a Struct
n Using Private Constructors
n Using Static Constructors
You have seen the basic elements of constructors. Constructors also have a
number of additional features and uses. In this section you will learn how to
initialize the data in objects by using constructors.
14 Module 9: Creating and Destroying Objects
Using Initializer Lists
n Overloaded Constructors Might Contain Duplicate Code
l Refactor by making constructors call each other
l Use the this keyword in an initializer list
class Date
{
...
public Date( ) : this(1970, 1, 1) { }
public Date(int year, int month, int day) { ... }
}
class Date
{
...
public Date( ) : this(1970, 1, 1) { }
public Date(int year, int month, int day) { ... }
}
You can use special syntax called an initializer list to implement one
constructor by calling an overloaded constructor.
Avoiding Duplicate Initia lizations
The following code shows an example of overloaded constructors with
duplicated initialization code:
class Date
{
public Date( )
{
ccyy = 1970;
mm = 1;
dd = 1;
}
public Date(int year, int month, int day)
{
ccyy = year;
mm = month;
dd = day;
}
private int ccyy, mm, dd;
}
Notice the duplication of dd, mm, and ccyy on the left side of the three
initializations. This is not extensive duplication, but it is duplication nonetheless,
and you should avoid it if possible. For example, suppose you decided to
change the representation of a Date to one long field. You would need to
rewrite every Date constructor.
Module 9: Creating and Destroying Objects 15
Refactoring Duplicate Initializations
A standard way to refactor duplic ate code is to extract the common code into its
own method. The following code provides an example:
class Date
{
public Date( )
{
Init(1970, 1, 1);
}
public Date(int year, int month, int day)
{
Init(day, month, year);
}
private void Init(int year, int month, int day)
{
ccyy = year;
mm = month;
dd = day;
}
private int ccyy, mm, dd;
}
This is better than the previous solution. Now if you changed the representation
of a Date to one long field, you would only need to modify Init. Unfortunately,
refactoring constructors in this way works some of the time but not all of the
time. For example, it will not work if you try to refactor the initialization of a
readonly field. (This is covered later in this module.) Object-oriented
programming languages provide mechanisms to help solve this known problem.
For example, in C++ you can use default values. In C# you use initializer lists.
Using an Initializer List
An initializer list allows you to write a constructor that calls another constructor
in the same class. You write the initializer list between the closing parenthesis
mark and the opening left brace of the constructor. An initializer list starts with
a colon and is followed by the keyword this and then any arguments between
parentheses. For example, in the following code, the default Date constructor
(the one with no arguments) uses an initializer list to call the second Date
constructor with three arguments: 1970, 1, and 1.
class Date
{
public Date( ) : this(1970, 1, 1)
{
}
public Date(int year, int month, int day)
{
ccyy = year;
mm = month;
dd = day;
}
private int ccyy, mm, dd;
}
This syntax is efficient, it always works, and if you use it you do not need to
create an extra Init method.
16 Module 9: Creating and Destroying Objects
Initializer List Restrictions
There are three restrictions you must observe when initializing constructors:
n You can only use initializer lists in constructors as shown in the following
example:
class Point
{
public Point(int x, int y) { ... }
// Compile-time error
public void Init( ) : this(0, 0) { }
}
n You cannot write an initializer list that calls itself. The following code
provides an example:
class Point
{
// Compile-time error
public Point(int x, int y) : this(x, y) { }
}
n You cannot use the this keyword in an expression to create a constructor
argument. The following code provides an example:
class Point
{
// Compile-time error
public Point( ) : this(X(this), Y(this)) { }
public Point(int x, int y) { ... }
private static int X(Point p) { ... }
private static int Y(Point p) { ... }
} |
|