C# Basic OOPs Concepts

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 operation 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 
  1. public class Client {  
  2.     public void Main() {  
  3.         var bll = new DataBll();  
  4.         bool status = bll.Save(data); // specific data to be saved   
  5.     }  
  6. }  
  7. public class DataBll {  
  8.     public bool Save(object data) {  
  9.         if (this.ValidateData()) {  
  10.             //save data in database   
  11.             return true;  
  12.         }  
  13.         return false;  
  14.     }  
  15.     private bool ValidateData() {  
  16.         // validation logic here  
  17.     }  
  18. }  
Here, the client is not aware of ValidateData() method in DataBll. This is called abstraction.
 

Encapsulation

 
Encapsulation is the concept of hiding data or method 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 "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 class are having 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 CalculatePF() method and inherit it from class Employee. We should not add CalculatePF() to Employee class because this method is useful only for PermanentEmployee class, not for the ContractualEmployee class.
 
Ex
  1. public class Employee {  
  2.     public void SaveEmployee() {}  
  3.     public List < EmployeeInfo > LoadEmployee() {}  
  4.     public void Pay() {}  
  5. }  
  6. public class PermanentEmployee: Employee {  
  7.     public int CalculatePF() {}  
  8.     // other methods applicable to only Permanent employee  
  9. }  
  10. public class ContractualEmployee: Employee {  
  11.     // other methods applicable to only Contractual employee   
  12. }  

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.
  1. Static Polymorphism
  2. Dynamic Polymorphism 
Static Polymorphism
 
The behaviour of this polymorphism is evaluated during compile time. Method overloading is an example of static polymorphism.
 
Ex:
  1. public class A {  
  2.     public int Add(int a, int b) {  
  3.         return a + b;  
  4.     }  
  5.     public int Add(int a, int b, int c) {  
  6.         return a + b + c;  
  7.     }  
  8. }  
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:
  1. public class Animal {  
  2.     public virtual string Eat() {  
  3.         return "grass";  
  4.     }  
  5.     public int LegsCount() {  
  6.         return 2;  
  7.     }  
  8. }  
  9. public class Dog: Animal {  
  10.     public override string Eat() {  
  11.         return "meat";  
  12.     }  
  13. }  
  14. public class Cat: Animal {  
  15.     public override string Eat() {  
  16.         return "milk";  
  17.     }  
  18. }  
  19. public class Goat: Animal {}  
  20. public class Cow: Animal {}  
  21. public class Start {  
  22.     public void main() {  
  23.         Animal dog = new Dog();  
  24.         Console.WriteLine(dog.Eat()); //  output- meat  
  25.         Animal cat = new Cat();  
  26.         Console.WriteLine(cat.Eat()); //output- milk  
  27.         Animal goat = new Goat();  
  28.         Console.WriteLine(goat.Eat()); //output - grass  
  29.         Animal cow = new Cow();  
  30.         Console.WriteLine(cow.Eat()); //output - grass  
  31.     }  
  32. }  
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 some food. We have to define the Eat() method individually in each class. Instead, we can define in parent and override only in Cat & Dog class.
 
I hope this helps you. In case you have any queries, please feel free to reply back to me.