Object Oriented Programming in C#

There are hundreds of tutorials on the subject of the OOP - Object Oriented Programming. Since they all begin with a strong emphasis on the technically-heavy features of the OOP, the approach may do more harm than good for a beginner, even if the motive of the author of the tutorials in question is to present it as the best as he or she can. In this context, this tutorial is going to follow a different path, way away from the well text-muted-beaten path.

 

OOP in C#

 

That means, the features of the OOP will be discussed along with the development of the classes.

Let's consider the following situation:

 

 

A collector wants to be a member of a particular antiques club. So, he wants to register himself by filling in an online form. If successful, a unique ID and a PIN will be sent by post. If he wants, he can register as a life member too - in order to become a special member; he has to fill in a different form for that purpose, though. Once registered, the member can login to the system and use the other services; for a life member, there is going to be a separate form for the same purpose.

This is a real life situation. The process of modelling the above with the use of software, leads to the concept of Object Oriented Programming - OOP.

To do that, let's recognize the nouns, their attributes and verbs.

 

 

A collector wants to be a member of a particular antiques-club. So, he wants to register himself by filling in an online form. If successful, a unique ID and a Pin will be sent by post. If he wants, he can register as a life-member too - in order to become a special member; he has to fill in a different form for that purpose, stating whether he is a life-member, though. Once registered, the member can login to the system and use the other services; for a life member, there is going to be a separate form for the same purpose.

In OOP terminology, the interpretation of what have been highlighted is as follows:

The nouns are objects - member, special member.

The verbs are methods or functions - register, login

The attributes are properties - memberID, Pin, islifeMember

The main elements are the objects. The methods and attributes are just parts of them. In order to model real-life objects - in this case, members - in OOP, we create a blueprint, which is known as a class.

The process of modelling an antiques collector in programming as a class, while assigning fields, properties and methods to it, is called Abstraction in the OOP.

Cookie-press and Cookie Analogy - a class and objects

In the following animation, the cookie press represents the class. It makes, of course, cookies - the objects.

cookie class

 

Although, there are several objects in this case, let's focus on only one of them - member. The blueprint for the member objects is the Member class.Its attributes and methods can be shown as follows:

Member

--------------------------------

Member ID

Pin

RegDate

--------------------------------

Login()

Register()

 

 

 

Member Class, Methods and Attributes

The member class, its methods, and attributes can be shown as follows:

public class Member
{
public string _regDate;
protected Guid _memberID;
public bool _islifeMember;
protected int _pin;

public Member()
{
}

public Member()
{
_regDate = DateTime.Now.ToShortDateString();
_memberID = Guid.NewGuid();
}

public string memberID
{
get
{
return _memberID.ToString();
}

}
public int Pin
{
get
{
return _pin;
}
set
{
_pin = value;
}
}

public string RegDate
{
get
{
return _regDate;
}
}

public bool islifeMember
{
get
{
return _islifeMember;
}
set
{
_islifeMember = value;
}
}

public StringBuilder registerMember(string cID, int cPin, string cDT)
{
cID = this.memberID.ToString();
cPin = this.Pin;
cDT = this.RegDate;
StringBuilder sb = new StringBuilder();
sb.Append(cID + cPin + cDT);
return sb;
}

public bool Login(Guid custId, int custPin)
{
if (custId == _memberID && custPin ==_pin)
{ return true; }
else
{ return false; }
}

public bool Login(string custId, int custPin,bool _islifeMember)
{
if (custId == memberID && custPin == Pin && _islifeMember==true)
{ return true; }
else
{ return false; }
}
}

Fields and Access Modifiers

The four variables - public string _regDate, protected Guid _memberID, public bool _islifeMember, protected int _pin, declared at the top of the class are known as fields in OOP.They store the data of an object, when created; public, private, protected are called access modifiers.

public
- variables can be accessed from any part in the code in the application or beyond
private
- variables can only be accessed by the code in the same class
protected
- variables can only be accessed by the code in the same class or a derived class from it - if the base class is Dad and the derived is Son both Dad and Son can access them.
friend
- variables can be accessed from anywhere in the application

In addition, string, int, bool and Guid are variable types in C#. Type GUID is particularly important, as it can create unique values, which are really important for distinct User IDs in a real-world application.

 

 

Constructors

The two Member() methods, just below the declaration of fields, are called Constructors in the OOP. They are the first methods to be initialized in the event of an object being created from a class. They are important, as the values to be initiated are always placed inside constructors.

The first constructor is called default Constructor, as it does not take any parameter. The second constructor is called parameterized Constructor, as it takes two parameters - _regDate and _memberID.

Thanks to the parameterized constructor, the date of registration and assigning a unique ID to a member can easily be achieved at the time of creating an object from a class, which is known in the OOP as Instantiation.

Properties

memberID, Pin, RegDate and IsLifeMember are called properties of the class. Their values can be set or obtained with the aid of the fields.

get
- gives values to the object, when created.
set
- sets values of the object.

If the property only contains get section, it is called readonly. Its value cannot be set through objects. The memberID, for instance, is readonly for obvious reasons: it cannot be altered externally!

On the other hand, if it only contains set section, it is called writeonly, as is only for setting the values and not reading from an object.

Since fields contain data without directly exposing them to outside world, this feature is known as Encapsulation in the OOP. _memberID, for instance, contains - and hides - the unique ID of a member object. In short, fields hide data inside a 'capsule'.

Please not that Encapsulation is not the same as Abstraction, although the distinction is pretty vague.

Methods

Methods are actions that the objects can perform.

Both registerMember and Login are methods; they can register member and let a member login after registration respectively. The methods, when act as functions, return a value. The Login method, for instance, return a Boolean value. Methods often need parameters.

Method Overloading

In the Member class, there are two methods with the same name - Login; both return a Boolean value. The number of parameters, however, is different: the first method contains two parameters and the second one contains three parameters. This is called Overloading in the OOP. The ability of the function Login to act in two different ways, in different needs, is called compile-time polymorphism:

poly
- many
morphs
- forms

Of course, the same could be achieved by declaring two different methods.Overloading, however, is more efficient as it makes the code more readable and minimizes the lines of code, which are vital in creating - and maintaining - a big application.

Instantiating Objects from a Class

Since the creation of the class, Member, is complete, let's create objects from this class. This is called instantiation.

 

 

Member cus = new Member(); // creating an object
cus.Pin = 1258; // assigning a value to a property of the object
cus.registerMember(string cus.memberID, int cus.Pin, string cus.RegDate); // adding members to the database of the club

The above procedure can be repeated to add members to a database, using the Member class. Please click the button to simulate what takes place in the database:

Please note the power of GUID - Globally Unique Identifier - creator; it generates unique IDs.

Inheritance

This is the process of extending the functions and properties of a class to its child classes.

In the above example, a lifeMember class is derived from Member class. The former inherits memberID, Pin, RegDate, registerMember() and Login() from the Member class. In addition, its own properties and methods can be defined as follows:

public class LifeMember : Member
// base class and derived class respectively {
public StringBuilder registerLifeMember(string cID, int cPin, string cDT, bool lifeMember)
{
cID = this.memberID.ToString();
cPin = this.Pin;
cDT = this.RegDate;
clifeMember = this.islifeMember;
StringBuilder sb = new StringBuilder();
sb.Append(cID + cPin + cDT + lifeMember);
return sb;
}

With the aid of the objects from lifeMember class, life members can be added to a separate database. In order to simulate it, please click the button below.

 

 

Method Overriding

Sometimes, there is a need of overriding a method in a base class, while using the same in the derived class. In order to achieve this, however, the method in question must be declared as virtual in the base class. Then override keyword is used in the derived class.

For example, if the Login() is to be overridden in the derived class, it must take the following form in the base class, and then in the derived class:

public virtual bool Login(Guid custId, int custPin) // in the base class
{
if (custId == _memberID && custPin ==_pin)
{ return true; }
else
{ return false; }
}

public class LifeMember : Member // base class and derived class respectively
{
public override Login(Guid custId, int custPin, string custislifeMem) // in the derived class
{
if (custId == memberID && custPin ==Pin && custisLifeMem == islifeMember)
{ return "Successful!"; }
else
{ return "Failed!"; }
}
}

The Login() method returns a different thing in the derived class, as it has been overridden by the 'new' Login() method in the derived class.

In the base class Login() returns a Boolean value, whereas in the derived class it returns a string, after being overridden.