Introduction to the Constructors of a Class
Introduction to the Constructors of a Class
Fundamentals of Constructors
Introduction
When you create an object (a variable declared from a class), you are in fact describing an object. In some cases, you may want that object to hold some default characteristics so that you don't have to work from scratch. A constructor is a special method that specifies the primary information of an object.
Practical Learning: Introducing Constructors
namespace Quadrilaterals2.Models { public class Square { private double s; public double Side { get => s; set => s = value; } public double Perimeter { get => s * 4; } public double Area { get => s * s; } } }
Creating a Constructor
A constructor is created as a special method with two main rules and one primary feature:
Here is an example of creating a constructor in a class named Square:
class Square
{
Square()
{
}
}
Remember that any method that doesn't have an access level is considered private. This is also valid for constructors. Although you can have private constructors in very extreme scenarios, most of the constructors you will create or use must be public (or internal). Here is an example:
class Square
{
public Square()
{
}
}
As we saw in the previous lessons, a class can have various types of members (such as fields, properties, and methods). Here is an example of a class that has some fields and a constructor:
class House
{
public House()
{
}
public string type;
public int beds;
public double value;
}
In the body of a class, the order of appearance of the members is not important. This means that you can first create a constructor followed by other members, first the members and a constructor last, or a constructor between members. Here is an example:
public class House
{
public int propNumber;
public double baths;
public House()
{
}
public string type
public int beds;
public double value;
}
A Constructor with a Parameter
In your class, you can create a constructor that uses a parameter. Here is an example:
public class Square
{
public Square(double side)
{
}
}
In the body of the class, you can ignore or use the parameter. One way you can use it is to pass its value to a member variable of the class. Here is an example:
public class Square { private double s; public Square(double side) { s = side; } }
Remember that the other members, such as methods, of the class can access any member of the same class. After creating the class, you can declare variables of it.
Creating an Object
Calling a Constructor
From our introductions, we know that, when declaring a variable of a class type, after the new operator, you must write the name of the class followed by parentheses. Here is an example we saw already:
House residence = new House();
public class House
{
public string type;
public int beds;
public double value;
}
In reality, when you declare a variable like that, you are actually calling the constructor of the class. As a result, the primary role of a constructor is to provide the default characteristics of an object created from a class. Therefore, in the body of a constructor, you can access each field and assign the desired value to it. Here is an example:
class House
{
public string type;
public int beds;
public double value;
public House()
{
type = "Single-Family";
beds = 5;
value = 495_680;
}
}
Practical Learning: Introducing Constructors
namespace Quadrilaterals2.Models
{
public class Square
{
private double s;
public Square(double side)
{
s = side;
}
public double Side
{
get => s;
set => s = value;
}
public double Perimeter
{
get => s * 4;
}
public double Area
{
get => s * s;
}
}
}
using Quadrilaterals2.Models; using static System.Console; WriteLine("====================================="); WriteLine("Enter the value to process the square"); Write("Side: "); double side = double.Parse(ReadLine()); Square sqr = new Square(side); WriteLine("====================================="); WriteLine("Geometry - Square Summary"); WriteLine("-------------------------------------"); WriteLine("Perimeter: {0}", sqr.Perimeter); WriteLine("Area: {0}", sqr.Area); Write("=====================================");
===================================== Enter the value to process the square Side: 248.73 ===================================== Geometry - Square Summary ------------------------------------- Perimeter: 994.92 Area: 61866.61289999999 ===================================== Press any key to close this window . . .
namespace Chemistry1.Models { public class Element { internal string Symbol { get; set; } internal string ElementName { get; set; } internal int AtomicNumber { get; set; } internal double AtomicWeight { get; set; } } }
An Object Without a Constructor
There are various ways to create an object. The most classic way is to start with the name of a class, assign the new operator followed by the name of the class again. Here is an example:
using static System.Console;
Trapezoid trap = new Trapezoid();
trap.Bottom = 1159.73;
trap.Top = 736.86;
trap.Height = 552.94;
WriteLine("===========================");
WriteLine("Trapezoid");
WriteLine("---------------------------");
WriteLine("Top: {0}", trap.Top);
WriteLine("Bottom: {0}", trap.Bottom);
WriteLine("Height: {0}", trap.Height);
WriteLine("---------------------------");
WriteLine("Area: {0}", trap.Area);
Write("===========================");
public class Trapezoid
{
private double _top_;
public double Bottom { get; set; }
public double Height { get; set; }
public Trapezoid()
{
Bottom = 0.00;
Height = 0.00;
}
public double Top
{
get
{
if (_top_ == 0.00)
return Bottom * .75;
return _top_;
}
set
{
_top_ = value;
}
}
public double Area
{
get
{
return ((Bottom + Top) / 2.00) * Height;
}
}
}
This would produce:
=========================== Trapezoid --------------------------- Top: 736.86 Bottom: 1159.73 Height: 552.94 --------------------------- Area: 524350.2373 =========================== Press any key to close this window . . .
When you use this technique, you can omit the constructor on the right side of the assignment operator. Here is an example:
using static System.Console;
Trapezoid trap = new();
// . . .
public class Trapezoid
{
// . . .
}
A Variable Object
When you are creating an object, you can omit the constructor on the left side of the assignment operator. In this case, you can replace the constructor with the var keyword. Also in this case, you must use the constructor on the right side of the assignment operator. Besides the var operator, you can also use the dynamic keyword. Here are examples:
using static System.Console; // A variable object var trap = new Trapezoid(); // A dynamic object dynamic zoid = new Trapezoid(); trap.Bottom = 1159.73; trap.Top = 736.86; trap.Height = 552.94; zoid.Bottom = 318.67; zoid.Top = 526.36; zoid.Height = 705.71; WriteLine("==========================="); WriteLine("Trapezoid"); WriteLine("---------------------------"); WriteLine("Top: {0}", trap.Top); WriteLine("Bottom: {0}", trap.Bottom); WriteLine("Height: {0}", trap.Height); WriteLine("---------------------------"); WriteLine("Area: {0}", trap.Area); WriteLine("==========================="); WriteLine("Trapezoid"); WriteLine("---------------------------"); WriteLine("Top: {0}", zoid.Top); WriteLine("Bottom: {0}", zoid.Bottom); WriteLine("Height: {0}", zoid.Height); WriteLine("---------------------------"); WriteLine("Area: {0}", zoid.Area); Write("==========================="); public class Trapezoid { private double _top_; public double Bottom { get; set; } public double Height { get; set; } public Trapezoid() { Bottom = 0.00; Height = 0.00; } public double Top { get { return (_top_ == 0.00) ? Bottom * .75 : _top_; } set { _top_ = value; } } public double Area { get => ((Bottom + Top) / 2.00) * Height; } }
This would produce:
=========================== Trapezoid --------------------------- Top: 736.86 Bottom: 1159.73 Height: 552.94 --------------------------- Area: 524350.2373 =========================== Trapezoid --------------------------- Top: 526.36 Bottom: 318.67 Height: 705.71 --------------------------- Area: 298173.06065 =========================== Press any key to close this window . . .
Introduction to Constructors and Properties
Initializing a Property Reader
A read property is referred to as read-only property because the clients of the class can only retrieve the value of the property but they cannot change it. Therefore, if you create a read property, you should provide the users with the ability to primarily specify the value of the field it represents. This would be a way to initialize the property readers.
To initialize a property reader, you can use a constructor of the class. To start, when creating the constructor, add a parameter to it. The parameter must be the same type as the property you want to initialize. Then, in the body of the constructor, assign the parameter to the private field associated with the property. This can be done as follows:
public class Square
{
private double _side;
public double Side
{
get
{
return this._side;
}
}
public Square(double s)
{
this._side = s;
}
}
Once a read property has been created, other classes can access it, for example they can read its value.
Initializing an Automatic Read-Only Property
Remember that an automatic property is one that is created with only the get or set contextual keyword without a body. An automatic read-only property is a property created with the get constextual keyword without a body Here is an example:
public class Employee
{
public string FullName { get; }
}
If you want to initialize an automatic read-only property, create a constructor. In the body of a constructor, assign the desired value to the property. Here is an example:
using static System.Console; Employee staff = new(); Write("Employee: "); WriteLine(staff.FullName); Write("================================="); public class Employee { public string FullName { get; } public Employee() { FullName = "Julius Nyerere"; } }
You cannot use a function or a method other than a constructor to initialize an automatic read-only property. As an alternative, to initialize an automatic read-only property, instead of using a constructor, after the curly brackets of the property, assign the desired default value. Here is an example:
public class Depreciation
{
public double Cost { get; } = 10000;
}
Initializing an Automatic Property
To initialize an automatic property, you can create a constructor that uses a parameter for the property. In the body of the constructor, assign the argument to the property. Here is an example:
public class Element
{
public int AtomicNumber { get; set; }
public Element(int number)
{
AtomicNumber = number;
}
}
In the same way, if you want the property to be initialized with any value of your choice, you don't have to include a corresponding value in the constructor. Instead, in the body of the constructor, you can assign any value you want. Here is an example:
public class Element
{
public int AtomicNumber { get; set; }
public Element()
{
AtomicNumber = 12;
}
}
Practical Learning: Initializing Automatic Properties
namespace Chemistry1.Models
{
public class Element
{
internal string Symbol { get; set; }
internal string ElementName { get; set; }
internal int AtomicNumber { get; set; }
internal double AtomicWeight { get; set; }
public Element()
{
Symbol = "H";
ElementName = "Hydrogen";
AtomicNumber = 1;
AtomicWeight = 1.008;
}
}
}
using Chemistry1.Models; using static System.Console; Element elm = new Element(); WriteLine("Chemistry"); WriteLine("------------------------"); WriteLine("Symbol: " + elm.Symbol); WriteLine($"Atomic Number: {elm.AtomicNumber}"); WriteLine("Element Name: " + elm.ElementName); WriteLine($"Atomic Weight: " + elm.AtomicWeight); Write("========================");
Chemistry ------------------------ Symbol: H Atomic Number: 1 Element Name: Hydrogen Atomic Weight: 1.008 ======================== Press any key to close this window . . .
Assigning a Default Value to an Automatic Property
Instead of initializing an automatic property in a constructor, you can assign the desired value after the curly brackets of the property. Here is an example:
public class Element
{
public int AtomicNumber { get; set; } = 12;
}
Practical Learning: Automatically Initializing Properties
namespace Chemistry1.Models { public class Element { internal string Symbol { get; set; } = "He"; internal string ElementName { get; set; }= "Helium" internal int AtomicNumber { get; set; } = 2; internal double AtomicWeight { get; set; } = 4.002602; } }
Chemistry ------------------------ Symbol: He Atomic Number: 2 Element Name: Helium Atomic Weight: 4.002602 ======================== Press any key to close this window . . .
A Required Initialized Property
Introduction
Consider a read-only property as follows:
using static System.Console;
House residence = new();
WriteLine($"Market Value: {residence.MarketValue}");
public class House
{
int price;
public int MarketValue
{
get
{
return price;
}
}
}
Obviously, this read-only property is not initialized, and there is no way to initialize the property. Of course, the alternative is to add a set clause and be able to initialize the property from there. Here is an example:
using static System.Console;
House residence = new();
WriteLine($"Market Value: {residence.MarketValue}");
public class House
{
int price;
public int MarketValue
{
get
{
return price;
}
set
{
price = value;
}
}
}
Notice that the above code makes it possible to initialize the property, but the property was not used without being initialized. Of course, now that the property has a set clause, you can initialize it. Here is an example:
using static System.Console;
House residence = new House();
residence.MarketValue = 450_000;
public class House
{
int price;
public int MarketValue
{
get
{
return price;
}
set
{
price = value;
}
}
}
WriteLine($"Market Value: {residence.MarketValue}");
If the property was not initialized, this means that if you did not, or forgot to, initialize the property, or you made a mistake of using or accessing a property that was not initialized, your code could lead to unpredictable behavior. There is an alternate or a solution to this type of situation.
Creating a Read-Write Property Initializer
Instead of the set contextual keyword, an alternative to create a property reader is with a contextual keyword named init. You primarily use it the same way you would proceed to create a set clause. Here is an example:
using static System.Console;
House residence = new();
WriteLine($"Market Value: {residence.MarketValue}");
public class House
{
int price;
public int MarketValue
{
get
{
return price;
}
init
{
price = value;
}
}
}
This time, to avoid the mistake of accessing a property that was not properly initialized, you must use a constructor (there are other means to initialize this type of property but we haven't studied them). To do this, create a constructor that uses a parameter that is the same type as the property. In the body of the constructor, initialize the property, which can be done by assigning it to the field that corresponds to the property. Then, when you create an object of the class, in the parentheses of the constructor, you must pass a value that initializes the property. Here is an example:
using static System.Console; House residence = new House(450_000); WriteLine($"Market Value: {residence.MarketValue}"); public class House { int price; public int MarketValue { get { return price; } init { price = value; } } public House(int cost) { price = cost; } }
An Automatic Property Initializer
We have already seen how to create an automatic read-write property with get and set clauses. Here is an example:
using static System.Console;
House residence = new();
residence.MarketValue = 450_000;
WriteLine($"Market Value: {residence.MarketValue}");
public class House
{
public int MarketValue
{
get;
set;
}
}
Notice that you can initialize the property because it has a set accessor. In the same way, you can create an automatic property with get and init clauses. Here is an example:
public class House
{
public int MarketValue
{
get;
init;
}
}
This time, if you want to initialize the property, you can (must) use a constructor that uses a parameter that you will assign to the property. Here is an example:
using static System.Console; House residence = new House(450_000); WriteLine($"Market Value: {residence.MarketValue}"); public class House { public int MarketValue { get; init; } public House(int price) { MarketValue = price; } }
Other Techniques of Creating an Object
A Default Constructor
We know that we can create a class without adding a constructor to it. Here is an example:
class House { string Location; string floorPlan; int Basement; }
When you set up a class, if you don't add a constructor, the compiler creates one for you. Whether you create this constructor or the compiler creates it for you, the constructor with empty parentheses is called the default constructor. If you want, you can create your own default constructor. To explicitly create a default constructor, create a method that holds the same name as the class and leave the parentheses of that constructor empty. Here is an example:
class House
{
public House()
{
}
}
If you are using Microsoft Visual Studio, to create a default constructor, right-click inside the class and click Insert Snippet... Double-click Visual C#. In the list that appears, double-click ctor:
The Code Editor would use the name of the class to create the constructor.
When you create an object of the class (by declaring a variable of that 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:
using static System.Console; BankAccount account = new BankAccount(); public class BankAccount { public BankAccount() { WriteLine("New Bank Account"); } }
This would produce:
New Bank Account Press any key to continue . . .
As you can see, even though the object was not used, just its creation was enough to call the default constructor. You may find it sometimes convenient to create your own constructor because, whether you create a default constructor or not, this does not negatively impact your program.
Practical Learning: Creating a Default Constructor
namespace Chemistry1.Models
{
public class Element
{
internal string Symbol { get; set; }
internal string ElementName { get; set; }
internal int AtomicNumber { get; set; }
internal double AtomicWeight { get; set; }
public Element()
{
}
}
}
Initializing the Members of a Class
If a class has a default constructor, when an object is created from that class, that default constructor is automatically called. This feature makes the default constructor a good place to initialize the members of the class. You have many options.
When creating a class, you can declare a member variable and initialize it in the body of the class. Here is an example:
public class Element
{
int AtomicNumber = 1;
}
Remember that a member created without the access level (public, private, or internal) is treated as private, and to re-inforce this, you can precede the member with the private keyword:
public class Element
{
private int AtomicNumber = 1;
}
In the same way, you can declare and initialize as many members as you want in the body of the class. Here are examples:
public class Element
{
string Symbol = "H";
int AtomicNumber = 1;
}
As an alternative, you can create fields in the class, then create a constructor and initialize the field(s) in the constructor.
Practical Learning: Creating a Constructor that Initializes
namespace Chemistry1.Models
{
public class Element
{
internal string Symbol { get; set; }
internal string ElementName { get; set; }
internal int AtomicNumber { get; set; }
internal double AtomicWeight { get; set; }
public Element()
{
AtomicNumber = 3;
Symbol = "Li";
AtomicWeight = 6.94;
ElementName = "Lithium";
}
}
}
Chemistry ------------------------ Symbol: Li Atomic Number: 3 Element Name: Lithium Atomic Weight: 6.94 ======================== Press any key to close this window . . .
Initializing an Object
With or without a constructor, you can specify the values of an object at any time. This means that, even if a class has a default constructor and you have created its object, to set the values of the members of the class, access each member and assign the desired value.
Practical Learning: Initializing an Object
using Chemistry1.Models; using static System.Console; Element be = new(); be.Symbol = "Be"; be.AtomicNumber = 4; be.ElementName = "Beryllium"; be.AtomicWeight = 9.0121831; WriteLine("Chemistry"); WriteLine("------------------------"); WriteLine("Symbol: " + be.Symbol); WriteLine($"Atomic Number: {be.AtomicNumber}"); WriteLine("Element Name: " + be.ElementName); WriteLine($"Atomic Weight: " + be.AtomicWeight); Write("========================");
Chemistry ------------------------ Symbol: Be Atomic Number: 4 Element Name: Beryllium Atomic Weight: 9.0121831 ======================== Press any key to close this window . . .
Creating a Whole Object
So far, we have seen that, to create an object, we can declare a variable of a class, then apply the period operator on the variable to access a property and assign a value to the property. This technique is used to initialize the properties one at a time. As a faster alternative, you can declare a variable of the class, initialize the object using the default constructor. Between the closing parenthesis and the semicolon, add an opening curly bracket and a closing curly bracket. In the curly brackets, add the name of a member of the class and initialize it with the value of your choice. Do the same for other desired members. You don't have to initialize each member and you don't have to list the members in the same order they appear in the class. The initializations must be separated by commas.
Practical Learning: Creating a Whole Object
using Chemistry1.Models; using static System.Console; Element be = new(); be.Symbol = "Be"; be.AtomicNumber = 4; be.ElementName = "Beryllium"; be.AtomicWeight = 9.0121831; Element b = new Element() { ElementName = "Boron", AtomicWeight = 10.81, AtomicNumber = 5, Symbol = "B" }; WriteLine("Chemistry"); WriteLine("------------------------"); WriteLine("Symbol: " + b.Symbol); WriteLine($"Atomic Number: {b.AtomicNumber}"); WriteLine("Element Name: " + b.ElementName); WriteLine($"Atomic Weight: " + b.AtomicWeight); Write("========================");
Chemistry ------------------------ Symbol: B Atomic Number: 5 Element Name: Boron Atomic Weight: 10.81 ======================== Press any key to close this window . . .
usiing Chemistry1.Models; using static System.Console; Element be = new(); be.Symbol = "Be"; be.AtomicNumber = 4; be.ElementName = "Beryllium"; be.AtomicWeight = 9.0121831; Element b = new() { ElementName = "Boron", AtomicWeight = 10.81, AtomicNumber = 5, Symbol = "B" }; Element c = new Element() { Symbol = "C", AtomicNumber = 6, ElementName = "Carbon", AtomicWeight = 12.011 }; WriteLine("Chemistry"); WriteLine("------------------------"); WriteLine("Symbol: " + c.Symbol); WriteLine($"Atomic Number: {c.AtomicNumber}"); WriteLine("Element Name: " + c.ElementName); WriteLine($"Atomic Weight: " + c.AtomicWeight); Write("========================");
Chemistry ------------------------ Symbol: C Atomic Number: 6 Element Name: Carbon Atomic Weight: 12.011 ======================== Press any key to close this window . . .
Requiring a Property Initialization
Remember that when you are initializing the properties of an object using the curly brackets delimiters, you can choose what properties to initiate and which ones to ignore. Here are examples:
using static System.Console; House town = new House() { PropertyNumber = 928_597, Bedrooms = 3, MarketValue = 385_600 }; House single = new House() { PropertyNumber = 404_852, Bedrooms = 5, Bathrooms = 3.5 }; House condo = new() { Bathrooms = 1.00, MarketValue = 248_590 }; WriteLine("Properties Listing"); WriteLine("======================"); WriteLine("Townhouse"); WriteLine("----------------------"); WriteLine("Property #: {0}", town.PropertyNumber); WriteLine("Bedrooms: {0}", town.Bedrooms); WriteLine("Bathrooms: {0:f}", town.Bathrooms); WriteLine("Market Value: ${0}", town.MarketValue); WriteLine("======================"); WriteLine("Single Family"); WriteLine("----------------------"); WriteLine("Property #: {0}", single.PropertyNumber); WriteLine("Bedrooms: {0}", single.Bedrooms); WriteLine("Bathrooms: {0:f}", single.Bathrooms); WriteLine("Market Value: ${0}", single.MarketValue); WriteLine("======================"); WriteLine("Condominium"); WriteLine("----------------------"); WriteLine("Property #: {0}", condo.PropertyNumber); WriteLine("Bedrooms: {0}", condo.Bedrooms); WriteLine("Bathrooms: {0:f}", condo.Bathrooms); WriteLine("Market Value: ${0}", condo.MarketValue); WriteLine("======================"); internal class House { internal int PropertyNumber { get; set; } internal int Bedrooms { get; set; } internal double Bathrooms { get; set; } internal int MarketValue { get; set; } }
Sometimes, you want the object initializer to always provide a value for a certain property. To let you indicate this, the C# language provides the required keyword. Therefore, to make sure the value of a certain property is always provided, precede the data type of the property with the required keyword. If you do that, whenever an object is created, the value of that property must be provided. If the value is not provided, the program would produce an error. Here is an example:
using static System.Console;
House condo = new() { Bathrooms = 1.00, MarketValue = 248_590 };
WriteLine("Properties Listing");
WriteLine("======================");
WriteLine("Condominium");
WriteLine("----------------------");
WriteLine("Property #: {0}", condo.PropertyNumber);
WriteLine("Bedrooms: {0}", condo.Bedrooms);
WriteLine("Bathrooms: {0:f}", condo.Bathrooms);
WriteLine("Market Value: ${0}", condo.MarketValue);
WriteLine("======================");
internal class House
{
internal required int PropertyNumber { get; set; }
internal int Bedrooms { get; set; }
internal double Bathrooms { get; set; }
internal int MarketValue { get; set; }
}
As a result, the abofe program would produce an error.
In your class, you can specify what property will require a value. This means that you don't have to mark all properties with the required keyword. Here are examples:
using static System.Console; House town = new House() { PropertyNumber = 928_597, Bedrooms = 3, MarketValue = 385_600 }; House single = new House() { PropertyNumber = 404_852, MarketValue = 650_775, Bedrooms = 5, Bathrooms = 3.5 }; House condo = new() { PropertyNumber = 630_958, Bathrooms = 1.00, MarketValue = 248_590 }; WriteLine("Properties Listing"); WriteLine("======================"); WriteLine("Townhouse"); WriteLine("----------------------"); WriteLine("Property #: {0}", town.PropertyNumber); WriteLine("Bedrooms: {0}", town.Bedrooms); WriteLine("Bathrooms: {0:f}", town.Bathrooms); WriteLine("Market Value: ${0}", town.MarketValue); WriteLine("======================"); WriteLine("Single Family"); WriteLine("----------------------"); WriteLine("Property #: {0}", single.PropertyNumber); WriteLine("Bedrooms: {0}", single.Bedrooms); WriteLine("Bathrooms: {0:f}", single.Bathrooms); WriteLine("Market Value: ${0}", single.MarketValue); WriteLine("======================"); WriteLine("Condominium"); WriteLine("----------------------"); WriteLine("Property #: {0}", condo.PropertyNumber); WriteLine("Bedrooms: {0}", condo.Bedrooms); WriteLine("Bathrooms: {0:f}", condo.Bathrooms); WriteLine("Market Value: ${0}", condo.MarketValue); WriteLine("======================"); internal class House { internal required int PropertyNumber { get; set; } internal int Bedrooms { get; set; } internal double Bathrooms { get; set; } internal required int MarketValue { get; set; } }
Still, if you want all properties to require a value, you can apply the required keyword to all of them. If you do that, whenever an object is created, a value must be provided for each property. Here is an example:
internal class House { internal required int PropertyNumber { get; set; } internal required int Bedrooms { get; set; } internal required double Bathrooms { get; set; } internal required int MarketValue { get; set; } }
Practical Learning: Creating a Whole Object
|
|||
Previous | Copyright © 2001-2024, FunctionX | Saturday 29 April 2023 | Next |
|