public class Normal {
public string name; // name is public
public String getName() {
return name ;
}
public String setName(String newName) {
name = newName ;
return name ;
}
public static void main(String args[]) {
Normal normal = new Normal();
normal.setName("suhail gupta");
System.out.println( "My name is : " + normal.getName() );
}
}
New class starts from here
public class Different {
private string name; // name is private
public String getName() {
return name ;
}
public String setName(String newName) {
name = newName ;
return name ;
}
public static void main(String args[]) {
Different different = new Different();
different.setName("suhail gupta");
System.out.println( "My name is : " + different.getName() );
}
}
First class has name declared public and other class has name declared private . Both the classes do the same work but only have access specifiers for name different . Now,
My questions are ?
- Do both the classes support encapsulation ? If they do , why are
privatepreferred overpublic? (I have done the same work declaring name public as i have done declaringprivate) - Which class is easier to maintain ?
- With which class programmers will be at ease during
refactoring? - How is
normalclass different , fromdifferentclass ? - When they say Unencapsulated means Unchangeable , how it is unchangeable here ?
In “
Normal” (there’s nothing “normal” about that), this is perfectly legal code:Your interface now includes a
Stringvalue calledname. Users will expect to be able to set it using either VarName.name or VarName.setName syntax. Users will expect to be able to retrieve it either with VarName.name or VarName.getName;For example, this is legal in “
Normal“:Now, maybe you’ll think “so what?” Imagine if the setting of the variable to null was separated from the actual printing (where the error happens) by 30 files. It will be very hard to know who screwed up the value of that variable. And there’s nothing you can do to prevent the user from screwing it up.
Now, if you had implemented
setNameas this:Then, the error happens immediately upon the user doing something wrong. The user tried to set a value to null that isn’t allowed to be null, therefore error. You have a call stack that shows where the error happened, and this is much easier to debug.
Of course, that doesn’t help because the user of “
Normal” does not have to usesetName. They are free to poke atnamedirectly.While it may technically be encapsulation, as far as I’m concerned, if the user can easily and trivially subvert it, it’s not encapsulation. If there’s no protection, there’s no encapsulation.
OK, let’s say you give me a library containing
Normal. I will use it in some way. Maybe I’ve gotNormalinstances scattered over 50 files. They all directly set and get the name by thenamerather than the accessors. This is perfectly legal because you made itpublic.Now, you decide, for whatever reason, that you don’t want to store the name in a string. Maybe you need to be able to have a first name and a last name. So, let’s say the next version of your library has this definition:
What’s missing?
public String name;That’s no longer available, because you now have a first and last name. Notice that the two accessor methods did not change at all.When I upgrade to the new version of your library, you will have just broken all of my code. I don’t like my code to be broken simply because you decided to change how you stored the data in your class. I will now never use anything you make again, because you can’t even keep your interface consistent from one version to the next.
And if you had just done things properly, none of that would have happened.