What are four principles of OOP, How aggregation is different than Composition?
Upasana | May 05, 2019 | 4 min read | 929 views
There are 4 major principles that make an language Object Oriented. These are Encapsulation, Data Abstraction, Polymorphism and Inheritance. These are also called as four pillars of Object Oriented Programming.
Encapsulation
Encapsulation is the mechanism of hiding of data implementation by restricting access to public methods. Instance variables are kept private and accessor methods are made public to achieve this. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.
To achieve encapsulation in Java −
-
Declare the variables of a class as private.
-
Provide public setter and getter methods to modify and view the variables values.
For example, we are hiding the name
and dob
attributes of person class in the below code snippet.
public class Employee {
private String name;
private Date dob;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
}
Relevance in multi-threading
Encapsulation is very important aspect worth consideration in multi-threading applications, in-fact if we start accessing the member variables directly without methods, there would be no way to make a class thread-safe. By synchronizing methods (or block of code), we can easily achieve thread-safety and make application behavior predictable in multi-threaded environment. Thus classes must use methods (even if they are just getter and setters) to share its internal state.
public class Counter {
private int c = 0; (1)
public synchronized void increment() {
c++;
}
public synchronized int getValue() { (2)
return c;
}
}
1 | member c must be kept private to Counter class, methods must be used to share internal state of counter. |
2 | Both increment() and getValue() must be synchronized to guarantee the correct behavior in multi-threaded environment. |
Abstraction
Abstract means a concept or an Idea which is not associated with any particular instance. Using abstract class/Interface we express the intent of the class rather than the actual implementation. In a way, one class should not know the inner details of another in order to use it, just knowing the interfaces should be good enough.
Inheritance
Inheritances expresses "is-a" and/or "has-a" relationship between two objects. Using Inheritance, In derived classes we can reuse the code of existing super classes.
In Java, concept of "is-a" is based on class inheritance (using extends
) or interface implementation (using implements
).
For example, FileInputStream
"is-a" InputStream
that reads from a file.
Polymorphism
It means one name many forms. It is further of two types - static and dynamic. Static polymorphism is achieved using method overloading and dynamic polymorphism using method overriding. It is closely related to inheritance. We can write a code that works on the superclass, and it will work with any subclass type as well.
Example
Java collections framework has an interface called java.util.Collection
, ArrayList
and TreeSet
are two different implementation of this interface. ArrayList maintains the insertion order of elements while TreeSet
orders its elements by their natural order
or comparator
(if supplied). Now if we write a method that accepts a collection and prints its elements, the actual object (ArrayList or TreeSet) at runtime will decide the behavior of this method.
public void print(Collection<String> collection) {
for (String s : collection) {
System.out.println("s = " + s);
}
}
Collection<String> collection1 = new ArrayList<>();
collection1.add("A");
collection1.add("D");
collection1.add("B");
collection1.add("C");
print(collection1); (1)
1 | elements will be printed as per the insertion order of elements into arraylist |
s = A s = D s = B s = C
Collection<String> collection2 = new TreeSet<>();
collection2.add("A");
collection2.add("D");
collection2.add("B");
collection2.add("C");
print(collection2); (1)
1 | elements will be printed as per the natural order |
s = A s = B s = C s = D
We just saw that print()
method’s behavior is determined by the actual type of object passed to it at run time. That’s polymorphism!
-
Other than objects of type
java.lang.Object
, all java objects are polymorphic i.e. they pass the IS-A test for their own type as well as for classObject
. -
A reference variable’s type determines the methods that can be invoked on the object that variable is referencing to. In the example above,
print()
method can only invoke methods that are listed onCollection
interface irrespective the type of actual object passed to this method. -
Polymorphic method invocation applies only to the instance methods (not to static methods, not to variables). Only overriden instance methods are dynamically invoked based on the real object’s type at runtime.
Top articles in this category:
- What is purpose of Collections.unmodifiableCollection
- What is difference between HashMap and HashSet
- What is polymorphism in Java OOP
- How will you increment each element of an Integer array, using parallel operation
- Discuss internals of a ConcurrentHashmap (CHM) in Java
- What will happen if we don't synchronize getters/accessors of a shared mutable object in multi-threaded applications
- Difference between Implementing Runnable and Extending Thread