"Hello, Amigo! I want to dedicate today's lecture to encapsulation. You already have a general idea of what it is."
So what are the advantages of encapsulation? There are many, but I will point out four that are, in my view, most important:
1) Valid internal state.
Programs frequently have several classes that interact with the same object. By interacting simultaneously with the object's internal data, they may violate the object's data integrity, causing the object to stop working correctly.
So the object must track any changes to its internal data, or better yet – it should be the one to make those changes.
If we don't want some class variable to be changed by other classes, then we declare it private, which means that only that class's methods can access it. If we want variables to be read-only for other classes, then we add public getter to these variables.
For example, we might want everybody to know how many elements there are in our collection, but nobody should be able to change it without our permission. In this case, we declare a variable private int count and a method public getCount().
Proper encapsulation guarantees that other classes cannot directly access our class's internal data and, consequently, cannot alter it without us being able to control their actions. They must call methods on the class that contains the variables that will be changed.
It's best to assume that other programmers will always use your classes in the way that is most convenient for them, not in the way that would be safest for you (or your class). This is a source of bugs, and a way to prevent them.
2) Parameter checking.
Sometimes you need to check the parameters passed into the methods of your class. For example, suppose we have a class that represents a "person" and you can specify its birth date. We should verify that any data passed in corresponds with the program's logic and the class's logic. For example, there is no 13th month, no February 30, etc.
"Why would somebody indicate a birth date of February 30?"
"Well, first of all, it could be the result of a data entry error."
Second, before a program works like clockwork, it may have lots of bugs. For example, something like this might happen.
A programmer writes code that determines who has a birthday the day after tomorrow. Let's say today is March 3. The program adds 2 to the current date and finds everybody who was born on March 5. So far, so good.
But when March 30 comes, the program doesn't find anybody, since there is no March 32. Programs are far less buggy when methods perform parameter checking."
"I remember when we studied ArrayList I looked at its code, and there were checks in the get and set methods to ensure that the index parameter is greater than or equal to zero and less than the length of the array. The code would throw an exception if the array didn't have an element corresponding to the index.
"Yep, that's classic input checking."
3) Fewer bugs when changing code inside classes.
Suppose we wrote a really helpful class as part of a huge project. Everybody like it so much that other programmers started using it in hundreds of places in their own code.
The class proved to be so useful that you decided to improve it. But if you get rid of any of the methods in the class, the code of dozens of other programmer will no longer compile. They would have to quickly rewrite their code. And the more rewriting that happens, the more opportunities there are for bugs. If you regularly break the build, you'll be hated.
But if we change methods marked as private, we know that these methods aren't called by anybody else's code anywhere. We can rewrite them, and change the number and type of parameters, and dependent code will still work. Or at least it will still compile.
4) We define how other objects will interact with our object.
We can restrict what actions can be taken on our object. For example, we might want only one instance of a class to be created—even if it is created in several places simultaneously in the project. And we can achieve this using encapsulation.
Encapsulation lets us impose additional restrictions that might turn into additional benefits. For example, the String class is implemented as an immutable object. An instances of the String class cannot be altered between its creation and its destruction. All methods of the String class (remove, substring, ...) return a new string and in no way change the object they are called on.
"Holy cow. So that's how it is."
"Encapsulation is intriguing."