Home

Class Construction

   

Introduction to Constructors

 

Description

Consider the following class:

public class BankAccount
{
    private string customerName;
    private decimal originalDeposit;
}

If you declare a variable of a class in your program, when the program comes up, the compiler reserves enough memory space for each member of the class. The memory space reserved for each member variable is filled with an initial value based on its type. For a string object, the space would be left empty. For an integer type, the space would be filled with 0. A better way to take care of this type is to provide a value whose role would be to initialize the member variables with the values of your choice.

 

A method that initializes an object can return any value but it is preferable to be of type void because its primary purpose is to reset the values. Since this method would give a starting value to all member variables that need to be initialized, it should have an equivalent argument for each of the member variables that it would initialize. Here is an example:

public class BankAccount
{
    private string customerName;
    private decimal originalDeposit;

    public void Initialize(string name, decimal deposit)
    {
    }
}

The method that initializes a class does not have to initialize all members of the class. To implement a method that initializes, simply assign its argument to the corresponding member variable of the class. Here are examples:

public class BankAccount
{
    private string customerName;
    private decimal originalDeposit;

    public void Initialize(string name, decimal deposit)
    {
        customerName = name;
        originalDeposit = deposit;
    }
}

You can then call the method after declaring the instance of the class to give initial values to its fields. Here is an example:

public class BankAccount
{
    private string customerName;
    private decimal originalDeposit;

    public void Initialize(string name, decimal deposit)
    {
        customerName = name;
        originalDeposit = deposit;
    }

    public void Show()
    {
        System.Console.WriteLine("Customer Account Information");
        System.Console.Write("Customer Name:    ");
        System.Console.WriteLine(customerName);
        System.Console.Write("Original Deposit: ");
        System.Console.WriteLine(originalDeposit);
    }
}

public class Exercise
{
    static int Main()
    {
        BankAccount account = new BankAccount();

        account.Initialize("Paul Motto", 450.00M);
        account.Show();

        return 0;
    }
}

This would produce:

Customer Account Information
Customer Name: Paul Motto
Original Deposit: 450.00
Press any key to continue . . .

Using a method that initializes, after initializing the object, you can use the values it holds as you see fit.

HomeApplication: Introducing Constructors

  1. Start Microsoft Visual Studio
  2. To create a new application, on the main menu, click File -> New Project
  3. In the middle list, click Empty Project
  4. Change the Name to DepartmentStore3 and click OK
  5. In the Solution Explorer, right-click DeparmentStore3 -> Add -> New Item...
  6. In the middle list of the Add New Item dialog box, click Code File
  7. Change the name to StoreItem and click Add
  8. In the file, type the following:
    public class StoreItem
    {
        public long itemNumber;
        public string itemName;
        public string size;
        public decimal unitPrice;
    }

The Default Constructor

A constructor is a special method that is created when the object comes to life. This particular method holds the same name as the class and it initializes the object whenever that object is created. When you create a class, if you don't declare a constructor, the compiler creates one for you; this is useful because it lets all other objects of the program know that the object exists. This compiler-created constructor is called the default constructor. If you want, you can create your own default constructor.

To create a constructor:

  • Declare a method that holds the same name as the class
  • Right-click inside the class and click Insert Snippet... Double-click Visual C#. In the list that appears, double-click ctor
     
    Constructor
     
    The Code Editor would use the name of the class to create the new method

Remember that the method must not return any value.

Here is an example:

public class BankAccount
{
    public BankAccount()
    {
    }
}

When you declare an instance of the class, whether you use that object or not, a constructor for the object is created. When an instance of a class has been declared, the default constructor is called, whether the object is used or not. This is illustrated in the following program:

public class BankAccount
{
    public BankAccount()
    {
        System.Console.WriteLine("New Bank Account");
    }
}

public class Exercise
{
    static int Main()
    {
        BankAccount account = new BankAccount();

        return 0;
    }
}

This would produce:

New Bank Account
Press any key to continue . . .

As you can see, even though the object was not used, just its declaration was enough to signal it. You might find it sometimes convenient to create your own constructor because, whether you create an empty constructor or not, this does not negatively impact your program.

ApplicationApplication: Using the Default Constructor

  1. In the Solution Explorer, right-click DepartmentStore3 -> Add -> New Item...
  2. In the middle list of the Add New Item dialog box, make sure Code File is selected.
    Change the name to DepartmentStore and click Add
  3. Change the document as follows:
    public class DepartmentStore
    {
        static int Main()
        {
            StoreItem si = new StoreItem();
    
            System.Console.WriteLine("Department Store");
            System.Console.Write("Item #:     ");
            System.Console.WriteLine(si.itemNumber);
            System.Console.Write("Item Name:  ");
            System.Console.WriteLine(si.itemName);
            System.Console.Write("Item Size:  ");
            System.Console.WriteLine(si.size);
            System.Console.Write("Unit Price: ");
            System.Console.WriteLine(si.unitPrice);
            
            System.Console.ReadKey();
            return 0;
        }
    }
    
  4. Execute the application. This would produce:
    Department Store
    Item #:     0
    Item Name:
    Item Size:
    Unit Price: 0
  5. Close the DOS window and return to your programming environment

The Constructor that Initializes

A constructor can be used to initialize the fields of a class. As such, a constructor provides a valuable alternative to a method that initializes, the type of method we saw earlier. To use a constructor to initialize the fields of a class, provide as arguments the necessary variables that you intend to initialize. You don't have to initialize all member variables in the constructor, only those that need to be initialized. In fact, you should initialize only those members that you think the other objects would need when using this object. This means that your object may have fields that, either the external objects don't need to modify (or access) or the member variable(s) will be initialized later when called from the needed object(s).

To implement a default constructor, you can just initialize the desired fields of the class. For a member variable of a numeric type, you can just assign the desired constant to each. If the variable is a character, assign a single-quoted symbol to it. If the variable is a string, then assign a double-quoted value to the variable. Here are examples:

public class BankAccount
{
    private string customerName;
    private decimal originalDeposit;

    public BankAccount()
    {
        customerName = "John Doe";
        originalDeposit = 0M;
    }

    public void Show()
    {
        System.Console.WriteLine("Customer Account Information");
        System.Console.Write("Customer Name:    ");
        System.Console.WriteLine(customerName);
        System.Console.Write("Original Deposit: ");
        System.Console.WriteLine(originalDeposit);
    }
}

public class Exercise
{
    static int Main()
    {
        BankAccount account = new BankAccount();

        account.Show();

        return 0;
    }
}

Here is an example of executing the program:

Customer Account Information
Customer Name:    John Doe
Original Deposit: 0
Press any key to continue . . .

ApplicationApplication: Creating a Constructor That Initializes

  1. On the main menu, click Window -> StoreItem.cs
  2. Change the file as follows:
    public class StoreItem
    {
        public long itemNumber;
        public string itemName;
        public string size;
        public decimal unitPrice;
    
        public StoreItem()
        {
            itemNumber = 0;
            itemName = "Unknown";
            size = "0";
            unitPrice = 0.00M;
        }
    }
  3. Execute the application to see the result
    Department Store
    Item #:     0
    Item Name:  Unknown
    Item Size:  0
    Unit Price: 0.00
  4. Close the DOS window and return to your programming environment

Constructor Overloading

The default constructor is the favorite place to provide default values to the members of a class. Besides the default constructor, you can add as many constructors as you judge necessary. This feature allows you to create various constructors for different reasons. This also means that the constructors of a class can be overloaded.

We have already reviewed all of the rules of method overloading. The most basic constructor you would create can use a single argument. When implementing a constructor that takes one argument, you should initialize the member that corresponds to the unique argument and initialize the other members with default values. Here is an example:

public class BankAccount
{
    private string accountNumber;
    private string customerName;
    private decimal originalDeposit;

    public BankAccount(string number)
    {
        accountNumber = number;
        customerName = "John Doe";
        originalDeposit = 0M;
    }

    public void Show()
    {
        System.Console.WriteLine("Customer Account Information");
        System.Console.Write("Account N#:       ");
        System.Console.WriteLine(accountNumber);
        System.Console.Write("Customer Name:    ");
        System.Console.WriteLine(customerName);
        System.Console.Write("Original Deposit: ");
        System.Console.WriteLine(originalDeposit);
    }
}

If you create a class with only one constructor as in the current example, when declaring an instance of the class, you must use that constructor: you cannot use the default constructor that doesn't take an argument. When declaring the variable, initialize it with a constructor with parentheses and provide the value(s) in the parentheses of the constructor. Here is an example:

public class BankAccount
{
    private string accountNumber;
    private string customerName;
    private decimal originalDeposit;

    public BankAccount(string number)
    {
        accountNumber = number;
        customerName = "John Doe";
        originalDeposit = 0M;
    }

    public void Show()
    {
        System.Console.WriteLine("Customer Account Information");
        System.Console.Write("Account #:        ");
        System.Console.WriteLine(accountNumber);
        System.Console.Write("Customer Name:    ");
        System.Console.WriteLine(customerName);
        System.Console.Write("Original Deposit: ");
        System.Console.WriteLine(originalDeposit);
    }
}

public class Exercise
{
    static int Main()
    {
        BankAccount account = new BankAccount("27-940025-17");

        account.Show();

        return 0;
    }
}

This would produce:

Customer Account Information
Account #:        27-940025-17
Customer Name:    John Doe
Original Deposit: 0
Press any key to continue . . .

In the same way, you can create different constructors for different initializations, although it would not be realistic to create a different constructor for each variable. If you create different constructors with different arguments to initialize (remember the rules of method overloading), when declaring the variable(s) for the class, make sure you initialize each instance with the right number of arguments; otherwise, the compiler would complain.

If you create a class with only one constructor and that constructor has at least one argument, the default constructor would not be available anymore. If you want to access a default constructor of an object, you have two alternatives:

  • If you don't create any constructor at all on a class, the default constructor would always be available whenever you invoke that class
  • If you create at least one constructor on a class and supply at least one argument to that constructor, you must explicitly create a default constructor for your class

ApplicationApplication: Overloading a Constructor

  1. On the main menu, click Window -> StoreItem.cs
  2. Change the file as follows:
    public class StoreItem
    {
        public long itemNumber;
        public string itemName;
        public string size;
        public decimal unitPrice;
    
        public StoreItem()
        {
            itemNumber = 0;
            itemName = "Unknown";
            size = "0";
            unitPrice = 0.00M;
        }
    
        public StoreItem(long number)
        {
            itemNumber = number;
            itemName = "Unknown";
            size = "0";
            unitPrice = 0.00M;
        }
    
        public StoreItem(long number, string name, string itemSize, decimal price)
        {
            itemNumber = number;
            itemName   = name;
            size       = itemSize;
            unitPrice  = price;
        }
    }
  3. Access the DepartmentStore.cs file and change it as follows:
    public class DepartmentStore
    {
        static int Main()
        {
            // Using the default contructor to create an unknown object
            StoreItem unknown = new StoreItem();
            System.Console.WriteLine("Department Store");
            System.Console.Write("Item #:     ");
            System.Console.WriteLine(unknown.itemNumber);
            System.Console.Write("Item Name:  ");
            System.Console.WriteLine(unknown.itemName);
            System.Console.Write("Item Size:  ");
            System.Console.WriteLine(unknown.size);
            System.Console.Write("Unit Price: ");
            System.Console.WriteLine(unknown.unitPrice);
            System.Console.WriteLine("=-------------------------------------------=");
    
            // Using the contructor that takes one argument create an object
            // whose only known information is the item number
            StoreItem knownNumber = new StoreItem(227174);
            System.Console.WriteLine("Department Store");
            System.Console.Write("Item #:     ");
            System.Console.WriteLine(knownNumber.itemNumber);
            System.Console.Write("Item Name:  ");
            System.Console.WriteLine(knownNumber.itemName);
            System.Console.Write("Item Size:  ");
            System.Console.WriteLine(knownNumber.size);
            System.Console.Write("Unit Price: ");
            System.Console.WriteLine(knownNumber.unitPrice);
            System.Console.WriteLine("=-------------------------------------------=");
    
            // Using the contructor that has all the information
            // necessary to create an object
            StoreItem complete = new StoreItem(180318,
                 "V-Neck Cardigan with Ruffle Trim", "M", 74);
            System.Console.WriteLine("Department Store");
            System.Console.Write("Item #:     ");
            System.Console.WriteLine(complete.itemNumber);
            System.Console.Write("Item Name:  ");
            System.Console.WriteLine(complete.itemName);
            System.Console.Write("Item Size:  ");
            System.Console.WriteLine(complete.size);
            System.Console.Write("Unit Price: ");
            System.Console.WriteLine(complete.unitPrice);
            System.Console.WriteLine("=-------------------------------------------=");
            
            System.Console.ReadKey();
            return 0;
        }
    }
  4. Execute the application to see the result
    Department Store
    Item #:     0
    Item Name:  Unknown
    Item Size:  0
    Unit Price: 0.00
    =-------------------------------------------=
    Department Store
    Item #:     227174
    Item Name:  Unknown
    Item Size:  0
    Unit Price: 0.00
    =-------------------------------------------=
    Department Store
    Item #:     180318
    Item Name:  V-Neck Cardigan with Ruffle Trim
    Item Size:  M
    Unit Price: 74
    =-------------------------------------------=
    Blouse
  5. Close the DOS window and return to your programming environment

A Constructor With Default Values

Since a constructor can take arguments and is primarily a method, its arguments can use default values. The rules are exactly the same we reviewed for optional values of arguments.

To provide a default value for the argument of a constructor, assign the desired but appropriate value to the argument when creating the constructor. Here is an example:

public class Rectangle
{
    private double len;
    private double hgt;

    public Rectangle(double side = 10.00D)
    {
    }
}

You can use the constructor to initialize the fields of the class.

If you create one constructor and it takes one argument, when creating an instance of the class, that single constructor would act as both (or either) a default constuctor and (or) a constructor that takes one argument. This means that you can declare a variable and use a constructor with empty parentheses. Here is an example:

public class Rectangle
{
    private double len;
    private double hgt;

    // Length = Height: Square
    public Rectangle(double side = 10.00D)
    {
        len = side;
        hgt = side;
    }

    public void Describe()
    {
        System.Console.WriteLine("Square Characteristics");
        System.Console.Write("Side: ");
        System.Console.WriteLine(len);
    }
}

public class Exercise
{
    static int Main()
    {
        Rectangle rect = new Rectangle();

        rect.Describe();

        return 0;
    }
}

This would produce:

Square Characteristics
Side: 10
Press any key to continue . . .

In the same way, you can create various constructors that take different arguments and some arguments can have default values. Different constructors can take different types of arguments or different numbers of arguments, some arguments can have default values while some other would not. When creating an object, know what constructor you are using. Here is an example:

public class Rectangle
{
    private double len;
    private double hgt;

    /* If the constructor is called with only one argument, 
     * we are dealing with a square.
     * If the constructor is called with two arguments,
     * then we have a rectangle */
    public Rectangle(double length, double height = 10.00D)
    {
        len = length;
        hgt = height;
    }

    /* If the constructor is called with only one argument, 
     * we are dealing with a square.*/
    public void Describe()
    {
        System.Console.WriteLine("Square Characteristics");
        System.Console.Write("Side: ");
        System.Console.WriteLine(len);
    }

    /* If the constructor is called with two arguments,
     * then we have a rectangle */
    public void Describe(int rect)
    {
        System.Console.WriteLine("Rectangle Characteristics");
        System.Console.Write("Length: ");
        System.Console.WriteLine(len);
        System.Console.Write("Height: ");
        System.Console.WriteLine(hgt);
    }
}

public class Exercise
{
    static int Main()
    {
        Rectangle rect = null;

        rect = new Rectangle(24.72);
        rect.Describe();

        rect = new Rectangle(24.72, 20.64);
        rect.Describe(1000);

        return 0;
    }
}

This would produce:

Square Characteristics
Side: 24.72
Rectangle Characteristics
Length: 24.72
Height: 20.64
Press any key to continue . . .

Using the Construction of a Class

 

The Destructor of a Class

As opposed to a constructor, a destructor is called when a program has finished using an object. A destructor does the cleaning behind the scenes. Like the default constructor, the compiler always creates a default destructor if you don't create one. Unlike the constructor, the destructor cannot be overloaded. This means that, if you decide to create a destructor, you can have only one. Like the default constructor, a destructor also has the same name as its class. This time, the name of the destructor starts with a tilde "~".

To create a destructor, type ~ followed by the name of the class. Here is an example:

public class BankAccount
{
    private string accountNumber;
    private string customerName;
    private decimal originalDeposit;

    public BankAccount(string number)
    {
        accountNumber = number;
        customerName = "John Doe";
        originalDeposit = 0M;
    }

    public void Show()
    {
        System.Console.WriteLine("Customer Account Information");
        System.Console.Write("Account #:        ");
        System.Console.WriteLine(accountNumber);
        System.Console.Write("Customer Name:    ");
        System.Console.WriteLine(customerName);
        System.Console.Write("Original Deposit: ");
        System.Console.WriteLine(originalDeposit);
    }

    ~BankAccount()
    {
    }
}

Read-Only Variables

When creating a member variable of a class, one of the decisions you make consists of deciding how the field would get its value(s). Sometimes you will allow the clients of the class to change the values of the field. In some other cases, you may want the field to only hold or present the value without being able to change it. This can still allow the clients to access the field and its value but on a read-only basis.

To create a field whose value can only be read, precede its data type, during declaration, with the readonly keyword. Here is an example:

public readonly double PI;

After declaring the variable, you should initialize it. You have two main alternatives. You can initialize the field when declaring it. Here is an example:

public class Circle
{
    public double radius;

    public Circle(double rad)
    {
        radius = rad;
    }

    public readonly double PI = 3.14159;
}

public class Exercise
{
    static int Main()
    {
        var circ = new Circle(24.72);

        System.Console.WriteLine("Circle Characteristics");
        System.Console.Write("Radius: ");
        System.Console.WriteLine(circ.radius);
        System.Console.Write("PI:     ");
        System.Console.WriteLine(circ.PI);

        return 0;
    }
}

This would produce:

Circle Characteristics
Radius: 24.72
PI:     3.14159

Press any key to continue . . .

Alternatively, you can initialize the field in the(a) constructor of its class. This would be done as follows:

public class Circle
{
    public double radius;

    public Circle(double rad)
    {
        radius = rad;
        PI = 3.14159;
    }

    public readonly double PI;
}

public class Exercise
{
    static int Main()
    {
        var circ = new Circle(24.72);

        System.Console.WriteLine("Circle Characteristics");
        System.Console.Write("Radius: ");
        System.Console.WriteLine(circ.radius);
        System.Console.Write("PI:     ");
        System.Console.WriteLine(circ.PI);

        return 0;
    }
}

If the value held by a read-only field is gotten from an expression, then the field must be initialized in the(a) construction with the desired expression. Based on this, the following code will not compile:

public class Circle
{
    public double radius;

    public Circle(double rad)
    {
        radius = rad;
        PI = 3.14159;
    }

    public readonly double PI;
    public readonly double Diameter = radius * 2;
}

public class Exercise
{
    static int Main()
    {
        var circ = new Circle(24.72);

        System.Console.WriteLine("Circle Characteristics");
        System.Console.Write("Radius:   ");
        System.Console.WriteLine(circ.radius);
        System.Console.Write("PI:       ");
        System.Console.WriteLine(circ.PI);
        System.Console.Write("Diameter: ");
        System.Console.WriteLine(circ.Diameter);

        return 0;
    }
}

This would produce:

Error	1	A field initializer cannot reference the non-static 
field, method, or property 'Circle.radius'	
C:\Exercise1\Exercise.cs	12	39	Bank

One solution to this error is to declare the field as read-only in the class and then initialize it in the(a) constructor with the expression. Here are a few examples:

public class Circle
{
    public double radius;

    public Circle(double rad)
    {
        radius = rad;
        Diameter = radius * 2;
        Circumference = Diameter * PI;
        Area = radius * radius * PI;
    }

    public readonly double PI = 3.14159;
    public readonly double Diameter;
    public readonly double Circumference;
    public readonly double Area;
}

public class Exercise
{
    static int Main()
    {
        Circle circ = new Circle(24.72);

        System.Console.WriteLine("Circle Characteristics");
        System.Console.Write("Radius:        ");
        System.Console.WriteLine(circ.radius);
        System.Console.Write("Diameter:      ");
        System.Console.WriteLine(circ.Diameter);
        System.Console.Write("Circumference: ");
        System.Console.WriteLine(circ.Circumference);
        System.Console.Write("Area:          ");
        System.Console.WriteLine(circ.Area);

        return 0;
    }
}

This would produce:

Circle Characteristics
Radius:        24.72
Diameter:      49.44
Circumference: 155.3202096
Area:          1919.757790656
Press any key to continue . . .

We know that a constant variable must be initialized when it is created. Although a read-only variable seems to follow the same rule, it doesn't. Remember that you don't need to initialize a read-only variable when you declare it since you can do this in the(a) constructor of the class. Also, because a constructor can be overloaded, a read-only field can hold different values depending on the particular constructor that is accessed at a particular time, but the value of a constant variable cannot change: it is initialized once, in the class (or in a method) and it keeps that value throughout the class (or method).

ApplicationApplication: Ending the Lesson

  1. Close your programming environment
  2. When asked whether you want to save, click No
 

Previous Copyright © 2010-2011 FunctionX Next