Introduction
As a beginner, when we start with C#, we mostly focus on how to write a piece of code. However, it's very important to know "Why" this approach and why not any other approach.
Let's begin with the basic OOPs concepts.
We have 4 basic principles in OOPs.
- Abstraction
- Encapsulation
- Inheritance
- polymorphism
Abstraction
Abstraction is the concept of showing only necessary data or operations to the calling client. It can be achieved using the encapsulation concept. Suppose we are trying to save data. The client will send data to a business logic class and business logic will expose only Save method to the client. But before saving any data, our application will have some validation. Business logic takes care of such validation, those methods are not exposed to the client.
Example
public class Client
{
public void Main()
{
var bll = new DataBll();
bool status = bll.Save(data); // specific data to be saved
}
}
public class DataBll
{
public bool Save(object data)
{
if (this.ValidateData())
{
//save data in database
return true;
}
return false;
}
private bool ValidateData()
{
// validation logic here
}
}
Here, the client is not aware of the ValidateData() method in DataBll. This is called abstraction.
Encapsulation
Encapsulation is the concept of hiding data or methods from the end client. We can achieve it using access modifiers, that is, by defining a property or method as private/protected etc we can control its visibility. In our previous example, ValidateData() is encapsulated by DataBll using a "private" access modifier, hence the Client class can't access it.
Inheritance
Inheritance is a concept of deriving a class from an existing class. We should use ":" for inheritance. In other words, if two classes have few common functionalities, define a parent class with common functions. Let the child class inherit the parent class and define its own functions.
Why do we need it?
Suppose we have class Employee with SaveEmployee, LoadEmployee and Pay methods. Now we want to calculate PF. Then we should create a class PermanentEmployee with the CalculatePF() method and inherit it from the class Employee. We should not add CalculatePF() to the Employee class because this method is useful only for the PermanentEmployee class, not for the ContractualEmployee class.
Ex
public class Employee
{
public void SaveEmployee() {}
public List<EmployeeInfo> LoadEmployee() {}
public void Pay() {}
}
public class PermanentEmployee : Employee
{
public int CalculatePF() {}
// other methods applicable to only Permanent employee
}
public class ContractualEmployee : Employee
{
// other methods applicable to only Contractual employee
}
Polymorphism
Polymorphism is a concept that can have different behaviour in different situations. The word Polymorphism itself means different forms. We have two types of polymorphism.
- Static Polymorphism
- Dynamic Polymorphism
Static Polymorphism
The behaviour of this polymorphism is evaluated during compile time. Method overloading is an example of static polymorphism.
Ex
public class A
{
public int Add(int a, int b)
{
return a + b;
}
public int Add(int a, int b, int c)
{
return a + b + c;
}
}
Here we have two methods named "Add", one adds two numbers and the other adds three numbers.
Why should we use Static polymorphism? Instead, we can define 2 methods with two different names.
Here we are trying to add numbers. If we define multiple method names, we will have to remember its implementation. But if we define a single method name as "Add" with different parameters, It's easy to find the method and based on our need we can pass parameters.
Dynamic Polymorphism
The behaviour of this polymorphism is evaluated during run time. Method overriding is an example of dynamic polymorphism. We need this behaviour when our application behaves differently in a different situation.
Ex
public class Animal
{
public virtual string Eat()
{
return "grass";
}
public int LegsCount()
{
return 2;
}
}
public class Dog : Animal
{
public override string Eat()
{
return "meat";
}
}
public class Cat : Animal
{
public override string Eat()
{
return "milk";
}
}
public class Goat : Animal
{
}
public class Cow : Animal
{
}
public class Start
{
public void main()
{
Animal dog = new Dog();
Console.WriteLine(dog.Eat()); // output- meat
Animal cat = new Cat();
Console.WriteLine(cat.Eat()); // output- milk
Animal goat = new Goat();
Console.WriteLine(goat.Eat()); // output - grass
Animal cow = new Cow();
Console.WriteLine(cow.Eat()); // output - grass
}
}
Here, we can see that the Animal class gives a different output.
Why should we use dynamic polymorphism?
Cat, Dog, Cow and Goat have the same number of legs. So we don't have to override it. But they don't eat any food. We have to define the Eat() method individually in each class. Instead, we can define in parent and override only in the Cat & Dog class.
I hope this helps you. In case you have any queries, please feel free to reply back to me.