Encapsulation versus abstraction

Let's pause for a minute again to have a look at this concept, as it confuses developers (and it is a bit confusing, so examples help a lot). Part of the problem stems from the definitions:

  • Abstraction: only showing what is necessary
  • Encapsulation: hiding complexity

If we had to think of a basic class to encrypt some text, we'd need to take a minute to decide exactly what the class must do. I would imagine that the class needs to:

  • Take a string value for the text
  • Have a method to encrypt the text

So, let's code this:

public class EncryptionHelper
{
public string TextToEncrypt = "";
public void Encrypt()
{
}
}

I also know that if I wanted to encrypt some text, that I would need a randomly generated byte array to salt the text to be encrypted. Let's add that method:

public class EncryptionHelper
{
public string TextToEncrypt = "";
public void Encrypt()
{
}
public string GenerateSalt()
{
Return "";
}
}

Now, taking a look at the class again, I realize that the encrypted text will need to be saved in a database. So, I add a method to do just that:

public class EncryptionHelper
{
public string TextToEncrypt = "";
public void Encrypt()
{
}
public string GenerateSalt()
{
return "";
}
public void SaveToDatabase()
{
}
}

If we had to implement this class, it would look something like this:

EncryptionHelper encr = new EncryptionHelper();
encr.TextToEncrypt = "Secret Text";
string salt = encr.GenerateSalt();
encr.Encrypt();
encr.SaveToDatabase();

Okay, but now we see that there is a problem. The salt needs to be used by the encryption method, so naturally we would think to add a parameter to the Encrypt() method to take the salt. We would therefore do the following:

public void Encrypt(string salt)
{
}

It is here that the code starts to become a bit blurred. We are calling a method on the class to generate a salt. We are then passing the salt we generated from the class, back to the class. Imagine a class with many more methods. Which methods need to be called when, and in what order?

So, let's take a step back and think. What exactly are we wanting to do here? We want to encrypt some text. Therefore, we just want the following:

public class EncryptionHelper
{
public string TextToEncrypt = "";
public void Encrypt()
{
}
}

This is what we call abstraction. Looking back at the definition of abstraction, what we are doing in code fits with the definition because we are only showing what is necessary.

Then what about the other methods in the class? Well, quite simply put...make them private. The developer implementing your class does not need to know how to encrypt a string of text. The developer implementing your class just wants to encrypt the string and have it saved. The code can then be encapsulated as follows:

public class EncryptionHelper
{
public string TextToEncrypt = "";
public void Encrypt()
{
string salt = GenerateSalt();
// Encrypt the text in the TextToEncrypt variable
SaveToDatabase();
}
private string GenerateSalt()
{
return "";
}
private void SaveToDatabase()
{
}
}

The code that calls the encrypt class is now also much simpler. It looks like this:

EncryptionHelper encr = new EncryptionHelper();
encr.TextToEncrypt = "Secret Text";
encr.Encrypt();

Again, this fits with the definition of encapsulation, which is to hide complexity.

Please note that the code in the preceding encryption example does not have any implementation. I was only illustrating a concept here. You are free to add your own implementation, should you want to.

Lastly, do not confuse abstraction with abstract classes. These are different things. Abstraction is a way of thinking. We will take a look at abstract classes in the next section.

So, take a 5-minute break, grab some fresh air or a cup of coffee, come back, and buckle up! It's about to get interesting.