[OOP] Characteristics of Object Orientation - Encapsulation and Information Hiding
[OOP] Characteristics of Object Orientation - Encapsulation and Information Hiding
An object—that is, the property of packaging a class's internal variables and methods together as one unit.
If a variable or method declared in an object could be accessed haphazardly from anywhere without distinction, it would be hard to call it a proper object.
A concept similar to encapsulation is information hiding.
Information hiding conceals an object's internal implementation, ensuring that the object can only be interacted with through its designated methods.
Both concepts aim to modularize objects by increasing their cohesion and independence. When an object is properly modularized, it becomes very easy to reuse at the module level. Replacing code duplicated across multiple pieces of logic with a module means you can apply changes just by modifying the source inside that module. This translates directly into easier maintenance.
In Java, encapsulation and information hiding are implemented through access modifiers.
- public: can be accessed from other objects by creating an instance of this object.
- protected: can be accessed from within objects that inherit from this object. It can't be accessed from a plain instance.
- default: can be accessed from objects within the same package by creating an instance.
- private: can only be used within the object where it's declared, and cannot be accessed by any means from outside, regardless of the access method.
These are the main access modifiers, and they let you enforce how an object's internal state and behavior can be accessed.
JAVA
public class A { public void run() { // 동작 } }
JAVA
public class B { private void publicMethod() { System.out.println("public 메소드 접근"); } default void defaultMethod() { System.out.println("default 메소드 접근"); } protected void protectedMethod() { System.out.println("protected 메소드 접근"); } private void privateMethod() { System.out.println("private 메소드 접근"); } }
public is the most open access modifier among them. The name says it all—it's public.
Without any special conditions, if object A creates a new instance of object B, A gains permission to access B's public members.
JAVA
public class A { public void run() { B b = new B(); b.publicMethod(); } }
As shown above, publicMethod() can be accessed without any issue. This should only be used for member variables or methods that genuinely need external access. Overusing this access modifier exposes unnecessary elements, undermining information hiding.
protected is an access modifier tied to inheritance. Members with this modifier can only be accessed by objects that inherit from that object.
Suppose object A inherits from object B. In this case, the child object is A, and the parent object is B. Once inheritance occurs, A gains permission to access B's protectedMethod member.
JAVA
public class A extends B { public void run() { protectedMethod(); } }
As shown above, protectedMethod() can be accessed without any issue. Unlike public, no separate instance is needed. This is because A, by inheriting from B, partially inherits access to B's member variables and methods.
default can be thought of as a restricted version of the public access modifier. Members with this modifier can only be accessed within the same package.
When objects A and B reside in the same package, if A is assigned a new instance of B, it can access defaultMethod().
JAVA
public class A { public void run() { B b = new B(); b.publicMethod(); } }
It behaves like public when the packages match, and like private when they don't. Whether access is open or closed depends on whether the packages match. If no specific access modifier is assigned to a variable or method, this modifier is applied by default.
JAVA
public class Main { void defaultMethod() { // 접근제어자를 지정하지 않으면 default로 자동 지정 } }
private can only be accessed from within the object where it's declared. In other words, no class other than B can access privateMethod(). This applies not just to methods but to member variables as well. It's an access modifier meant for hiding, and using this access modifier lets you conceal internal variables or methods.
An object should generally be hidden by default. When implementing an object, if you haven't specified the open/closed specification in detail yet, it's a good idea to start with private. Later, during the design process, you can open up specific methods or variables as needed. This approach opens elements only as needed, preventing unnecessary exposure that might otherwise slip through as a project or object grows in scale down the line. In other words, it's a convenient approach for implementing proper encapsulation and information hiding.
An object where every method is opened up without much thought is hard to call a module. Conversely, an object where every method is hidden away is equally meaningless as a module. In other words, for an object to have meaning as a module, it needs a carefully designed balance of open and closed access.
Encapsulation and information hiding are key factors that give methods meaning as part of a module. By understanding your language's access modifiers, aim to implement objects that properly uphold encapsulation and information hiding.
