Encapsulation And Abstraction, Same Or Different?

When I first began to learn object oriented programming, I learned that there are three tenets of OOP – Encapsulation, Inheritance and Polymorphism. However, I have also seen other authors who opine that there is actually a fourth – Abstraction. One question now comes to mind: Is encapsulation the same as abstraction?
I decided to dig a little deeper, and I have come to realize that there’s a subtle difference between the two concepts, and this is what I have briefly presented in this article.
Wikipedia defines encapsulation thus: “Encapsulation refers to the bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object's components.”
Encapsulation helps us hide the actual state of an object from the outside world**. The outside world is only able to access public methods which modify the state of the object. Take a look at the example below, for instance.
  1. class Program  
  2. {  
  3.     //Demonstrating Encapsulation  
  5.     static void Main(string[] args)  
  6.     {  
  7.         Dog dog = new Dog();  
  8.         dog.Feed();  
  9.         dog.Abandon(2);  
  10.     }  
  11. }  
  13. class Dog  
  14. {  
  15.     public Dog()  
  16.     {  
  17.         hungerLevel = 10;  
  18.     }  
  20.     public void Feed()  
  21.     {  
  22.         hungerLevel--;  
  23.     }  
  25.     public void Abandon(int numberOfDays)  
  26.     {  
  27.         hungerLevel += numberOfDays*10;  
  28.     }  
  30.     private int hungerLevel;  
  31. }  
  1. class Program  
  2. {  
  3.     // Demonstrating Abstraction  
  5.     static void Main(string[] args)  
  6.     {  
  7.         Dog dog = new Dog();  
  8.         Daughter.FeedDog(dog);  
  9.     }  
  10. }  
  12. class Daughter  
  13. {  
  14.     static public void FeedDog(Dog dog)  
  15.     {  
  16.         GoToMarket();  
  17.         BuyDogFood();  
  18.         dog.Feed();  
  19.     }  
  21.     private static void GoToMarket()  
  22.     {  
  23.         //Logic here  
  24.     }  
  26.     private static void BuyDogFood()  
  27.     {  
  28.         //Logic here  
  29.     }
  31. }  
The dog object has a private field – hungerLevel, and two public methods – Feed and Abandon. Ideally, we cannot access the hunger level of a dog directly. We can only alter the hunger level by feeding it, or by abandoning it for a few days.
In C#, when we access the public properties of a class, we are actually accessing getters and setters which are special methods. The getters and setters now modify the private fields. So in the same way, the private fields (defining the object's state) cannot be directly modified by the outside world.
Abstraction on the other hand refers to hiding complex implementations. Think of your phone for instance. You only have a few buttons you can press to perform certain actions. How these actions are performed, you don't really care. How the pressing of a button sends signals that are converted to bits and bytes that the computer can understand, you don't need to know. All you want is functionality. Similarly, we can hide properties and methods from the outside world (by making them private to just the class), and then we expose only certain methods that "encapsulate" all that complexity for the client to access.
The code snippet above shows an example of abstraction. The dog owner instructs his Daughter to feed the dog. The Daughter knows she has to go to market and buy dog food, but all the dog owner needs is that the dog should be fed. Other activities are simply “abstracted” beneath the FeedDog method.
So we can conclusively say that abstraction can be seen in a certain sense as an extension of the concept of encapsulation but from a broader perspective.
Thank you for reading. Please feel free to let me know your thoughts in the Comments section. Also check out my previous articles on Specification Pattern in C# and Composite Specifications.
**The state of an object is defined by the value of all its private fields at every instance.