OOPs Concepts In Java

Deepti Swain
11 min readNov 11, 2021

--

Fig 1. Object-Oriented Programming (OOPS) in Java ~ by Deepti Swain

Object-Oriented Programming System (OOPs) is a programming concept that works on the principles of objects at the centre of your program. OOPs is at the core of Java, and hence it is best to understand its basic principles before you begin writing even simple Java programs. Therefore, let’s begin with a discussion of the OOPs concept.

If you are a beginner in Java programming I would recommend you to learn certain basics such as Class, Object, Method, Access Modifiers, Interface etc. which will make it easier and relatable to understand the following oops concept.

1. Encapsulation:

The process of grouping/binding data members(variables) and corresponding methods into a single unit is called Encapsulation. If any component follows data hiding and abstraction, then the component is said to be encapsulated. The encapsulation principle says hiding the data behind a method. Every Java class is an example of encapsulation.

So let’s see what is this data hiding and abstraction in detail.

i) Data Hiding: An outside person can not access out internal data directly, this concept of OOPS is called data hiding. After successful validation/authentication, an outside person can access our internal data. The main advantage is Security.

How to Implement data hiding in Java?

We can implement data hiding by declaring data members(variables) as private.

Example: We can not access our bank balance directly even if we are a valid customer of the bank. We need certain validation such as username, password etc. A simple program demonstrating data hiding.

public class Account {
// Data Hiding (Outside class cannot access balance as it is private //data member.)
private double balance ;
public double getBalance() {
Scanner scan = new Scanner(System.in);
System. out.println("Provide your Username" );
String Username = scan.nextLine();
System. out.println("Provide Your password" );
String Password = scan.nextLine();
if (Username .equals("Adwet" ) && Password.equals( "Deep")) {
balance = 3500000;
} else {
System. out.println("Invalid username or password" );
}
return balance ;
}
}
//Driver Class
public class GetBalance {
public static void main(String[] args) {
Account acnt = new Account();
double d = acnt.getBalance();
//accessing getBalance method, //doing certain validation only we will be able to fetch balance.
System. out.print("The balance is: " +d );
}
}

ii) Abstraction:

Hiding Internal implementation, just highlighting the set of services that we are going to offer is the concept of abstraction. By using the interface and abstract classes we can implement abstraction.

Abstraction gives us a range of advantages such as Outside person doesn’t view our internal implementation and hence provide Security. Enhancement is become very easy, as we can use any kind of language or enhancement in internal implementation without disturbing GUI, hence user experience remains seamless. Maintainability, Easiness to use etc.

Example: By using a GUI screen an ATM machine provides us with a set of services whereas internal implementation is not highlighted.

Fig 2: OPPS- Piller1: Encapsulation ~by Deepti Swain

Advantage of Encapsulation: Security, Enhancement becomes easier, maintainability, modularity etc.

Disadvantage of Encapsulation: It increases the line of code due to getter, setter method, validation logic etc, and hence it becomes time-consuming, performance becomes down.

Tightly Encapsulated Class: Every variable present in the class is private, then such type of class is called a tightly encapsulated class. If the parent class is not tightly encapsulated then no child class is tightly encapsulated.

2. Inheritance

Inheritance is also known as the IS-A relationship, says all the methods and variables available in the parent class are available in child class but not vice-versa. By using extends keyword we can implement inheritance. Example: In Java, Object Class is the parent class of all other classes.

Certain Rule of Inheritance:

public class DemoInheritance {
public static void main(String[] args) {
// Rule 1. Parent reference can be used to hold Parent object. And able to access only the parent class methods.
Parent p = new Parent();
p.m1(); // correct
p.m2(); // Compile time error: The method m2() is undefined for //the type Parent
//Rule 2. Child reference can be use to hold child object and able to access both parent and child class methods.
Child c = new Child();
c.m1();
c.m2();
//Rule 3. Parent reference can hold child class object
Parent po = new Child(); //(correct)
po.m2(); //but method available in child still we will not be able to access. Compile time error: The method m2() is undefined for the type Parent.
//Rule 4. Child reference can not hold parent class object
Child cc = new Parent(); // Compile Time error: Type mismatch: cannot convert from Parent to Child
}
}
class Parent {
void m1() {
System.out.print("Parent method running" );
}
}
class Child extends Parent {
void m2() {
System. out.print("Child method running" );
}
}

Types of Inheritance:

Fig 3: OPPS- Piller 2: Inheritance ~ by Deepti Swain

There are 5 types of inheritance concepts available.

  1. Single Inheritance: Single child class extends single parent class.
  2. Multi-level Inheritance: Single child class extend another child class which extends a parent class.
  3. Hierarchical Inheritance: Multiple child class extends single parent.
  4. Hybrid Inheritance: Combination of above 4 inheritance.
  5. Multiple Inheritance: Single child class extends multiple parent class. This is not supported by Java because if two class contains two methods with the same name, then when the child class extends both parent class following multiple in-inheritance an ambiguity arises which class method to pick. Hence, Java doesn’t support multiple inheritances and hybrid inheritance in class. This problem is also called as diamond access problem. However, in the case of interface, multiple inheritance is supported in java because in the case of inheritance each class just contains the declaration and the corresponding implemented class only implements the method, hence there is no chance of ambiguity.
Fig 4: Multiple Inheritance in case of Java Interface Deepti Swain

Advantage of Inheritance: The main advantage is code re-usability. Always write the common methods for all other child classes in the parent class. Inside child class only write those methods which are specific to that child class.

3. Polymorphism

Poly means many, morphs means forms. One name multiple forms are called polymorphism. Overriding and Overloading are examples of polymorphism.

There are two types of polymorphism available in java:

  1. Static Polymorphism /Compile time Polymorphism / Early Binding: This is the concept of Overloading.
  2. Dynamic Polymorphism /Run time Polymorphism / Late Binding: This is the concept of Overriding.

i) Overloading: Methods having the same method name but different argument type is the concept of Java method overloading. In overloading, method resolution(which method to execute) takes care by the compiler based on reference type and not based on a run-time object. Hence it is also called Compile Time polymorphism/ Early Binding / Static polymorphism.

Parent p = new Child();
p.m1(); // Reference type class that is Parent class m1() gets //executed and not the runtime object class(i.e Child class m1())

Rules Of Over Loading:

Rule 1: In overloading, if the exact matched method is not available, the compiler won’t give an immediately compile-time error, it promoted the argument to the next data type and if the matched method gets then it provides that output. Eg. In the below program t.m1(‘a’); from Char data type to compiler will promote to int type and execute the m1(int i) method. This concept is called automatic promotion in overloading.

Order of data type promotion:

byte → short → int → long → float → double

char → int → long → float → double

class DemoOverloading {public void m1() {
System. out.println("No argument method executed." );
}
public void m1(int i) {
System. out.println("Int argument method executed." );
}
public void m1(float f) {
System. out.println("Float argument method executed." );
}
public static void main(String[] args) {
DemoOverloading dd = new DemoOverloading();
dd.m1();
// O/P: No argument method executed.
dd.m1(10);
// O/P: Int argument method executed.
dd.m1(323.89f);
// O/P: Float argument method executed.
dd.m1( 'a');
// O/P: Int argument method executed. ----------> Here //the compiler promoted char to int
//dd.m1(10.5);
//O/P: The method m1( int) in the type //DemoOverloading is not applicable for the arguments (double).
//------>if promotion is not possible like here 10.5 is double. //double to next level promotion is not possible hence we are //getting compile time error.
}
}

Rule 2: In overloading exact match gets higher priority. If both parent and child classes are available, then the first compiler checks in child class and if the argument is available in child class it executes the child class. For eg. in the below program dd.m1(null). ‘null’ is available in both Object and String class but as the child class get the highest priority hence, m1(String s) method executes. In case child class is not available or in the child class, the argument is not available then parent class executes.

class DemoOverloading2 {public void m1(Object o) {
System. out.println(“Object version method executed.” );

}
public void m1(String s) {
System. out.println(“String version method executed.” );
}
public static void main(String[] args) {
DemoOverloading2 dd = new DemoOverloading2();
dd.m1( new Object());
// o/p: Object version method executed.
dd.m1( “Test”);
// o/p: String version method executed.
dd.m1( null);
// o/p: String version method executed.
//Here String argument method is executed because it is the child //class of object. If child class doesn’t match the argument then //only we will go for parent class
}
}

Rule 3: If there is no relationship between arguments compiler can not decide which method to execute and throws an error. Example: String and StringBuffer (both are child classes of the Object class but have no relation with each other). Hence, the compiler gets ambiguity for dd.m1(null); and throws Compile time error.

class DemoOverloading3 {public void m1(int i) { // general method 1.0 ver
System. out.println("General method executed." );
}
public void m1(int... a) { // var argument method, (any number of //int argument is accepted.)
System. out.println("Var argument method executed." );
}
public static void main(String[] args) {
DemoOverloading3 dd = new DemoOverloading3();
dd.m1(12); // o/p: General method executed.
dd.m1(90,89,0); // o/p: Var argument method executed.
dd.m1(); // o/p: Var argument method executed.
}
}

ii) Overriding: In java, all the methods available in the parent class is available to the child class but if the child class is not satisfied with the method then the child class re-defines/re-writes a method available in parent class, this concept is called as overriding. The parent class method which is over-ridden is called as Overridden method whereas the child class method which overriding is called as an overriding method. In the overriding method resolution always takes care by JVM based on run time object and not based on the reference type. Hence, overriding is also considered as Runtime Polymorphism / Late Binding / Dynamic polymorphism.

Parent p = new Child();
p.m1(); //Object type class that is Child class m1() gets executed //and not the reference type object class(i.e //Parent class m1())

Rules of Overriding:

Rule 1:

Fig 5. Rule 1: Method Signature Same and Covarient Return Type~by Deepti Swain

Method signature must be same.(Method name and argument type along with argument type sequence must be same.) Same or Co-variant return type is allowed. Covariant return type means child class return type need not be same as parent class return type, its child types also allowed.

class Parent1 {
public Object m1() {
// same method signature
return null ;
// return type null is Object type.
}
}
class Child1 extends Parent1{
public String m1() {
// same method signature
return null ;
// return type null is String type. String is child //class of Object class.
}

Rule 2:

Fig 6. Rule 2: Overriding is Not applicable in Private Methods~by Deepti Swain

Private methods are only visible/accessible inside the class only, hence parent class private methods are not visible to the child class. Thus, the overriding concept is not applicable for private methods.

Rule3:

Fig 7. Rule 3: Overriding is Not applicable in FinalMethods of Parent class~by Deepti Swain

Final method in parent class can not be override.

Rule 4: In overriding the scope of method can not be reduce, increase the scope is acceptable. If child class method throws any checked exception then compulsory the parent class method should through the same checked exception or its parent exception. Otherwise compile time error we will get saying method can not be override. For unchecked exception there is no restriction. Child class can throws any number of unchecked exception.

Rule 5: Both parent and child class methods should be non-static in-order to achieve method overriding. Method resolution is taken care by JVM based on run type object. Note: In case both parent and child class methods are static then it is called as method hiding. Here compiler is responsible for method resolution based on reference type.

Rule 6: Var arg method is a method where it can take any number of argument. Var arg method can be override with another var arg method only(not with normal method).

class Parent2 {public void m1(int… i) { // same method signature
System. out.println(“Returning var arg method of parent.” );
}
}
class Child2 extends Parent1 {
public void m1(int i) {
// Not same method signature, hence it //become overloading and not overriding. And hence it becomes //compile time polymorphism.
System. out.println(“Returning var arg method of parent.” );
}
class Child3 extends Parent1{
public void m1(int… i) {
// same method signature as both parent and //child are var argument method, hence it become overriding. Hence //it become run time polymorphism.
System.out.println( “Returning var arg method of parent.”);
}

Rule 7: Overriding method is applicable only for method and not variables. Variable resolution always takes care by compiler hence the method will be picked based on reference type. Defining same variable in child class is called variable hiding or shadowing.

public class DemoOverriding {
public static void main(String[] args) {
Parent1 p = new Parent1();
System. out.println(p .s );
// o/p: Parent
Child1 c = new Child1();
System. out.println(p .s );
// o/p: Child
Parent1 pc = new Child1();
System. out.println(p .s );
// o/p: Parent
}
}
class Parent1 {
String s = “Parent”;
}
class Child1 extends Parent1{
String s = “Child”;
}

Let’s end up the polymorphism concept with a quick note on the properties of overloading and overriding.

Fig 8. Properties of Overloading & Overriding concept ~by Deepti Swain

OOPs in java provides the ability to simulate real-world event much more effectively using the concept of encapsulation which gives the data security, inheritance which makes the code reusable followed by easy maintainability and polymorphism which gives us more flexibility in order to design and write the program.

In my upcoming blog, I will discuss some basic concepts as well as advanced concepts related to OOPs in Java. If you have any feedback or questions, you can post them in the comments section. I’ll be happy to hear from you.

--

--