Encapsulation is a similar idea to Abstraction. It deals with restricting access to components of an object. A good analogy would be airport security. You're not allowed to bring certain things in (weapons), and you're not allowed to take (steal) certain things from the airport.
A programming example of this would be this:
public class ComputeSqrt { private double number; public ComputeSqrt(double number) { setNumber(number); } public void setNumber(double number) { if (number >= 0) { this.number = number; } } public double getNumber() { return this.number; } public double computeSqrt() { return Math.sqrt(this.number); } }
I realize that this is a completely pointless class, but It demonstrates in very simple terms a use of encapsulation. Here, the outside isn't allowed to access number because they could potentially set it to a negative number. Instead, Getters and Setters are used to determine what kind of access is allowed on number. In terms of Efficiency/Optimization, this technique is almost unnoticeable, and should be utilized as much as possible (obviously with different conditions based on the needs).
Pretty much anything can be encapsulated: fields, methods, constructors, even other classes.
The example for encapsulating a field was given above. Here, we'll encapsulate the constructors of a class. To do so, we use what are called "factory constructors". Factory constructors create an object when certain parameters are met, and don't when they aren't, as opposed to regular constructors which always create the object. for comparison, we'll compare it with the above ComputeSqrt class.
public class ComputeSqrt2 { private double number; private ComputeSqrt2(double nonNegativeNumber) { this.number = nonNegativeNumber; } public ComputeSqrt2 createObject(double number) { if (number < 0) { return null; } else { return new ComputeSqrt2(number); } } //... rest of methods }
Here, we can see the advantage right away: the ComputeSqrt object is always created, but it's unknown what it means when a negative number is passed to the constructor. For ComputeSqrt2, the object is only created if a valid input is used. This can save some memory, especially if you have to create tons of objects, or objects that are quite large.
I won't talk too much about encapsulating classes here, just know that it's similar to encapsulating fields. You can declare classes inside a class, but there is this limitation:
You can't declare a purely public class inside another public class
public class DoIt1 { // Illegal! public class DoIt2 {} }
You can however, declare public static classes inside another public class.
I'm not sure if you can declare abstract classes or not, someone else want to shed light on this?
Here are some questions about encapsulation that should help you understand what you do and don't know about encapsulation. If you can answer all of them correctly, you probably have a good understanding of encapsulation
1. What is the primary purpose of encapsulation?
2. How do we encapsulate an idea?
3. Is this a proper way of encapsulating an idea:
public class SomeClass { private int a; public SomeClass(int a) { this.a = a; } public int getA() { return a; } }
Why or why not?
Here are the answers to the above questions.
1. To direct access to a particular part of an object/class, generally fields, but methods and even classes can be encapsulated.
2. We can encapsulate with methods and classes.
3. Yes, it is. In this case, there is only a getter method for a. This means that the outside can not change the value of a. In this case, it isn't all that useful, but there will be cases where you want an internal field to be unchangeable to the outside, but changeable inside the class.
2. We can encapsulate with methods and classes.
3. Yes, it is. In this case, there is only a getter method for a. This means that the outside can not change the value of a. In this case, it isn't all that useful, but there will be cases where you want an internal field to be unchangeable to the outside, but changeable inside the class.