Skip to main content

OOPS Fundamentals

OOPS CONCEPTS IN JAVA

⇒ OOPS Overview

  • OOPs means object oriented programming.
  • Here object means real world entity like Car, ATM, Bike etc.
Procedural Programming OOPS (Object-Oriented Programming)
Program is divided into parts called functions. Program is divided into objects.
Doesn't provide a way to hide data, gives importance to function and data moves freely. Objects provide data hiding, gives importance to data.
Overloading is not possible. Overloading is possible.
Inheritance is not possible. Inheritance is possible.
Code reusability does not present. Code reusability is present.
Eg:- Pascal, C, FORTRAN etc. Eg:- Java, C#, Python, C++ etc.

⇒ Objects & Classes

  • Object has 2 things :-

    • Properties or State
    • Behavior or Function
  • For Example:-

    • Dog is an object because:-
      • Properties like: Age, Colour, breed etc.
      • Behavior like: Bark, sleep, eat etc.
    • Car is an object because it has :-
      • Properties like Colour, Type, Brand, Weight etc.
      • Behavior like Apply brake, Drive, Increase speed etc.
  • Class is a blueprint / skeleton of an object.

    • To create an object, a Class is required.
    • So, class provides the template or blueprint from which an Object can be created.
    • From class, we can create multiple objects.
    • To create a class, use keyword class:
  • Eg:-

    class Student {
        // Data Variables
        int age;
        String name;
        String address;
    
        // Data Method
        void updateAddress() {
            // logic to update address
        }
    
        // Data Method
        int getAge() {
            return age;
        }
    }
    
    // Now let's create an object of type Student.
    Student engstu = new Student();
    

⇒ 1st Pillar of OOPS - Data Abstraction

  • It hides the internal implementation and shows only essential functionality to the user.

  • It can be achieved through Interface and abstract classes.

  • Example:-

    • Car: we only show the BRAKE pedal, and if we press it, Car speed will reduce. But HOW? That is ABSTRACTED from us.
    • Cellphone: how a call is made, that is ABSTRACTED to us.
  • Advantages of Abstraction:-

    • It increases Security & confidentiality.
  • DEMO:-

    interface Car {
        public void applyBrake();
        public void incSpeed();
        public void handbrake();
    }
    
    class CarImpl implements Car {
        public void applyBrake() {
            // Internal steps:
            // step-1
            // step-2
            // step-3
            // Car stops.
            System.out.println("Brake applied, car stopping.");
        }
    
        public void incSpeed() {
            // Implementation
            System.out.println("Speed increasing.");
        }
    
        public void handbrake() {
            // Implementation
            System.out.println("Handbrake applied.");
        }
    }
    
    // So when user calls applyBrake(), internally it's invoking step-1,
    // step-2 --- but all that is hidden from the user but ultimately
    // car stops.
    
    // So this improves security as user is not aware of the
    // internal functionality and only knows about the result.
    

⇒ 2nd Pillar of OOPS - DATA ENCAPSULATION

  • Encapsulation bundles the data & code working on that data in a single unit.

  • Also known as DATA-HIDING.

  • Steps to achieve encapsulation:

    • Declare variables of a class as private.
    • Provide public getters & setters to modify & view the values of the variables.
  • Advantages of encapsulation:-

    • Loosely coupled code
    • Better access control & security.
  • DEMO:

    class Dog {
        private String colour; // private variable
    
        // public getter
        public String getColour() {
            return this.colour;
        }
    
        // public setter
        public void setColour(String colour) {
            this.colour = colour;
        }
    }
    
    // Now let's create an object of Dog type
    Dog lab = new Dog();
    lab.setColour("black");
    System.out.println(lab.getColour()); // will return black
    
    // So here we haven't given the access of the variable 'colour'
    // of class Dog. Instead we did it with the help of one getter & setter
    // which in turn have the access of variable.
    

⇒ 3rd Pillar of OOPS - INHERITANCE

  • Capability of a class to inherit properties from their parent class.

  • It can inherit both functions and variables so that we don't have to write them again in the child class.

  • Can be achieved using extends keyword or through interface (for type inheritance).

  • Types of inheritance:-

    • Single inheritance
    • Multilevel inheritance
    • Hierarchical inheritance
    • Multiple inheritance (Not actually supported by Java for classes due to diamond problem, but through interfaces, we can achieve a form of it or solve the diamond problem for interfaces).
  • Advantages Of Inheritance:

    • Code reusability
    • We can achieve polymorphism using inheritance.
  • DEMO:- (Parent Class)

    // Vehicle (Parent)
    //   ↓
    // Car (Child)
    
    class Vehicle {
        boolean engine;
    
        public Vehicle() {
            this.engine = true; // Default engine to true
        }
    
        public boolean getEngine() {
            return this.engine;
        }
    }
    
    class Car extends Vehicle {
        String type;
    
        public Car(String type) {
            super(); // Calls Vehicle constructor
            this.type = type;
        }
    
        public String getCarType() {
            return this.type;
        }
    }
    
    // Now let's create an object of Car.
    Car swift = new Car("Hatchback");
    System.out.println(swift.getEngine());    // Accessing parent method
    System.out.println(swift.getCarType());   // Accessing own method
    
    Vehicle vehicle = new Vehicle();
    // vehicle.getCarType(); // Should not work - Parent cannot access child-specific method
    

    So, since swift is an object of Car which extends Vehicle, hence it can call getEngine(). Whereas vice versa isn't possible.

  • Visualizing Inheritance Types:

    • Single Inheritance
      Class A
        ↓
      Class B
      
    • Multilevel Inheritance
      Class A
        ↓
      Class B
        ↓
      Class C
      
    • Hierarchical Inheritance
        Class A
       /     \
      ↓       ↓
      

    Class B Class C ```

    • Multiple Inheritance (via interfaces in Java)

      Interface A   Interface B
         \       /
          \     /
           Class C  (implements A, B)
      

      (Direct class-to-class multiple inheritance like Class C extends Class A, Class B is not supported in Java due to the diamond problem. This is typically visualized with a cross over the direct inheritance lines from two parent classes to one child class.)

      This is not supported in Java due to diamond problem but there is a workaround for it using interfaces.


⇒ 4th Pillar of OOPS - POLYMORPHISM

  • Poly means "Many" & morphism means "Form".

  • A same method, behaves differently in different situations.

  • Example:

    • A person can be farmer, husband, employee etc. (different roles)
    • Water can be liquid, solid or gas. (different forms)
  • Types of polymorphism:-

    • Compile Time / Static Polymorphism / Method Overloading
    • Run Time / Dynamic Polymorphism / Method Overriding
  • DEMO: Method Overloading (Compile-Time Polymorphism)

    class Sum {
        // Method 1
        int doSum(int a, int b) {
            return a + b;
        }
    
        // Method 2 (Overloaded)
        int doSum(int a, int b, int c) {
            return a + b + c;
        }
    }
    
    // So this practice of creating methods with same name but
    // different parameters is known as overloading.
    // So the method will be called based on the parameters.
    
  • DEMO: Method Overriding (Run-Time Polymorphism)

    class A {
        int getEngine() {
            return 1; // Represents some base engine value
        }
    }
    
    class B extends A {
        @Override // Good practice to use this annotation
        int getEngine() {
            return 2; // Represents a different engine value for B
        }
    }
    
    // Now let's create an object of class B
    B objB = new B();
    System.out.println(objB.getEngine()); // This 'll return 2
    
    A objA = new B(); // Parent reference, child object
    System.out.println(objA.getEngine()); // This will also return 2 (Runtime polymorphism)
    
    // So which method to call is decided at runtime & this is known as
    // method overriding.
    // So, in overriding, everything i.e. arguments, return type,
    // method name is same (or compatible for return type - covariant).
    

⇒ Relationships

  • Is-a relationship

    • Achieved through inheritance.
    • Example: DOG is-a animal.
    • Inheritance forms an is-a relation between its parent and child classes.
  • Has-a relationship

    • Whenever an object is used as an instance variable in another class, it's called a HAS-A relationship (also known as Composition or Aggregation).
    • Relationship could be:
      • one-to-one
      • one-to-many
      • many-to-many
    • Example:
      • School has students.
      • Bike has an engine.
      • School has classes (classrooms/courses).
    • Association: relationship between 2 different objects.
      • Aggregation - Both objects can survive individually, means ending of one object will not end another object. (e.g., A Department has Professors. If department closes, professors can still exist). It represents a "has-a" relationship but a weak one.
      • Composition - Ending of one object will end another object. (e.g., A House has Rooms. If the house is demolished, the rooms cease to exist). It represents a strong "has-a" relationship.