Wednesday 18 April 2012

Initializing Data.

We can use special syntax called an initializer list to implement one constructor by calling an overloaded constructor.




Avoiding Duplicate Initializations
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 we should avoid it if possible. For example, suppose we decided to change the representation of a Date to one long field. We would need to rewrite every Date constructor.
Refactoring Duplicate Initializations
A standard way to refactor duplicate 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.
Using an Initializer List
An initializer list allows you to write a constructor that calls another constructor in the same class. We 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 we use it we do not need to create an extra Init method.
Initializer List Restrictions
There are three restrictions we must observe when initializing constructors:
We 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) { }
}
We 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) { }
}
We 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) { ... }
}

0 comments: