[3] Intro to Object-oriented programming - 4 Basic Principles of OOP

[3] Intro to Object-oriented programming - 4 Basic Principles of OOP

Dec 3, 2022
The following are my notes on the 4 basic principles of OOP (Object-oriented programming) based on Kunal Kashwaha’s lectures on YouTube (link in the reference section)

The 4 Basic Principles

1. Inheritance

2. Polymorphism

3. Encapsulation

4. Abstraction

Mnemonic to remember the above:
IPEA: I Paid Eighty American (dollars)


Why is inheritance important?
  • code reuse because subclasses inherits the variables and methods of superclass.
extends keyword used in Java to inherit from a parent class
Parent class (also called Base class or Super class)
public class Animal { private boolean isCarnivore; private int noOfLegs; public Animal(){} public Animal(boolean isCarnivore, String food, int legs){ this.isCarnivore = isCarnivore; this.noOfLegs = legs; } }
Child class (also known as Sub class or Derived class)
public class Cat extends Animal{ private String color; public Cat(boolean isCarnivore, String food, int legs) { super(isCarnivore, food, legs); this.color="White"; } public Cat(boolean isCarnivore, String food, int legs, String color){ super(isCarnivore, food, legs); this.color=color; } }
Example of main program:
public class AnimalInheritanceTest { public static void main(String[] args) { Cat cat = new Cat(true, "milk", 4, "black"); System.out.println("Cat is carnivore?" + cat.isVegetarian()); System.out.println("Cat eats " + cat.getEats()); System.out.println("Cat has " + cat.getNoOfLegs() + " legs."); System.out.println("Cat color is " + cat.getColor()); } } //OUTPUT: Cat is carnivore? true. Cat eats milk. Cat has 4 legs. Cat color is black.
Use cases of thesuper keyword:
  1. To initialize the data members (variables) belonging to the parent class in the constructor of the child class
// This is the constructor of the Child class public Cat(boolean isCarnivore, String food, int legs) { super(isCarnivore, food, legs); this.color="White"; }
  1. When the variable name is same, super keyword can be used to refer to the data member belonging to the parent class
ex: super.member
  1. super( ) always refers to the constructor in the closest superclass.
  1. If super( ) is not used in child class constructor, then the default or parameterless constructor of each superclass is executed.

Types of inheritances:

Single Inheritance

public class A { ... .. ... }; public class B extends A { ... .. ... };

Multi-level inheritance

public class A { ... .. ... }; public class B extends A { ... .. ... }; public class C extends B { ... ... ... };

Multiple inheritance (not supported by Java)

Hierarchical Inheritance

public class A { ... .. ... }; public class B extends A{ ... .. ... }; public class C extends A { ... .. ... }; public class D extends A { ... .. ... };

Points to remember:

  1. You can only specify one superclass for any subclass that you create.
  1. No class can be a parent class of itself.
  1. Every class has “Object” class as a superclass in Java.
  1. A superclass variable can be used to reference any object derived from that class.
A parent class’s variable can reference to child class’ object
Parent ref = new Child();
The type of the reference variable—not the type of the object that it refers to, determines what members or functions can be accessed.
// Parent class class Box { private double width; private double height; private double depth; // construct clone of an object Box() { // pass object to constructor this.width = 0; this.height = 0; this.depth = 0; } }
// Child class class BoxWeight extends Box { double weight; // weight of box // construct clone of an object BoxWeight() { // pass object to constructor this.weight = 0; } }
public static void main(String args[]){ Box ref = new BoxWeight(); // In this case ref can access to width, height and depth variables because it is of type BOX // and it cannot access weight. }

Using final keyword with Inheritance

Use case 1: to Prevent Overriding
To disallow a method from being overridden, specify final as a modifier at the start of its declaration.
Why to use final? Methods declared as final can sometimes provide a performance enhancement because the compiler is free to inline calls to them. Compiler “knows” they will not be overridden by a subclass’ function. This is called early-binding: function call resolved at compile time.
Concept of Late-binding: Usually Java resolves calls to methods dynamically, at run time, when final is not used.
Use case 2: to Prevent Inheritance
When a class is declared as final, then it cannot be inherited. NOTE: Declaring a class as final implicitly declares all of its methods as final, too.
It is illegal to declare a class as both abstract and final since an abstract class is incomplete by itself and it relies on the subclasses to provide complete implementations.

Using static keyword with Inheritance

static means data member doesn’t depend on the object.
Although static methods can be inherited, there is no point in overriding them in child classes because the parent class’ method will run even if we try to override it.


Poly: many
morphism: shapes/forms

Two types of polymorphism

  1. Compile time polymorphism - achieved through method/function overloading
  1. Dynamic polymorphism - achieved through method/function overriding

1. function overloading

It is possible to define two or more methods within the same class that share the same name as long as the parameter declarations are different.
Java will employ its automatic type conversions only if no exact match is found.
When Java encounters a call to an overloaded method, it simply executes the version of the method whose parameters matches the arguments used in the call.
class Arithmetic{ int cube(int x){ return x*x*x; } double cube(double x){ return x*x*x; } float cube(float x){ return x*x*x; } public static void main(String[] args){ Arithmetic myMultiplication = new Arithmetic(); System.out.println("The cube of 5 is " + myMultiplication.cube(5)); System.out.println("The cube of 5.0 is " + myMultiplication.cube(5.0)); System.out.println("The cube of 0.5 is " + myMultiplication.cube(0.5)); } //OUTPUT The cube of 5 is 125 The cube of 5.0 is 125.0 The cube of 0.5 is 0.125

2. function overriding

Only occurs when the names and the type signatures of the two methods are identical.
In a class hierarchy, when a method in a child class has the same name and type signature as a method in its parent class, then the child class method overrides the parent class method.
When an overridden method is called from within the same child class, it will always refer to the version of that method defined by the child class.

Dynamic Method Dispatch:

Dynamic method dispatch is the mechanism by which a call to an overridden method is resolved at run time (and not compile time)
When an overridden method is called through the parent class’s reference, Java determines which version of that method to execute based on the type of the object being referred to at the time the call occurs.
In this case, it is the type of the object being referred to (not the type of the reference variable) that determines which version of an overridden method will be executed.

Encapsulation vs Abstraction

Hides the code and data into a single entity or unit so that data can be protected from the outside world
Hides unnecessary detail but shows essential information to the user
Solves the issue at implementation level
Solves an issue at the design level
focuses on internal working
focuses on external outlook
implemented by using access modifiers
implemented using abstract classes and interfaces
getters and setters are used to hide the data
abstract classes and interfaces used to hide complexities
process of containing information
process of gaining information