Four Principles In Object-orientated Programming

The four principles of OOP are: Encapsulation, Inheritance, Polymorphism, and Abstract. Let’s introduce each principle in the following paragraphs.

It is study note from Educative.io

  • Encapsulation

    • Definition

      It refers to binding the data and the methods to control that data together in a single class. It hides the data and the method of the object from the outside.

    • Illustration

      All variables in a class should be private. And we define public methods that are called as getter and setter to access or modify the variables.

      encapsulation-principle

    • Advantages

      • It is easy to manage the class.
      • We can specify which data member we want to hidden or accessible.
      • We can decide which variables have read/write privileges(Increase flexibility).
      • It is security because other classes can not modify data without permission.
    • Example

      A user class is modeled as:

      Having userName field;

      Having password field;

      A method named login() to grant access.

      • Java OOP

        class User {
        // private variables/data
        private String userName;
        private String password;
        public User(String userName, String password){
        this.userName = userName;
        this.password = password;
        }
        public void login(String userName, String password){
        // check if the userName and password match
        if(this.userName.toLowerCase().equals(userName.toLowerCase()) && this.password.equals(password)){
        System.out.println("You are granted access!");
        } else {
        System.out.println("Invalid userName or Password");
        }
        }
        public static void main(String[] args){
        User user = new User("wing", "123");
        user.login("wing", "124"); // Invalid userName or Password
        user.login("wing", "123"); // You are granted access!
        }
        }
      • Python OOP

        class User:
        def __init__(self, userName=None, password=None):
        # fake private field
        self.__userName = userName
        self.__password = password
        def login(self, userName, password):
        # check userName and password if they are matched
        if((self.__userName.lower() == userName.lower()) and (self.__password == password)):
        print("You have access")
        else:
        print("Invalid userName or password")
        user = User("wing", "123")
        # Invalid userName or password
        user.login("wing", "124")
        # You have access
        user.login("wing", "123")
  • Inheritance

    • Definition

      It provides a way to create a new class(subClass) from a existing class(superClass). And the new class inherits all the non-private fields and methods of the existing class.

      It uses extends and overriding keyword.

    • Illustration

      This is A relationship.

      inheritance-principle

    • Advantages

      • Inheritance makes the code reusable(Re-usability).
      • Avoiding duplicate of code.
      • SubClass can extend SuperClass logic(Extensibility).
      • SuperClass can keep some data private, it also named data hiding.
    • Example

      • Java OOP

        // Super Class
        class Vehicle {
        // private fields
        private String make;
        private String color;
        private int year;
        private String model;
        // Constructor
        public Vehicle(String make, String color, int year, String model) {
        this.make = make;
        this.color = color;
        this.year = year;
        this.model = model;
        }
        // method
        public void printDetails() {
        System.out.println(this.make +" "+this.color +" "+ this.year+" "+this.model);
        }
        }
        // Sub Class
        class Car extends Vehicle {
        // private fields
        private String bodyStyle;
        // Constructor
        public Car(String make, String color, int year, String model, String bodyStyle) {
        super(make, color, year, model);
        this.bodyStyle = bodyStyle;
        }
        public void carDetails() {
        printDetails();
        System.out.println(bodyStyle);
        }
        }
        class Main {
        public static void main(String[] args) {
        Car car = new Car("Weilai", "Blue", 2020, "SUV", "Cool Style");
        // Weilai Blue 2020 SUV
        // Cool Style
        car.carDetails();
        }
        }
      • Python OOP

        class Vehicle:
        def __init__(self, make, color, model):
        self.make = make
        self.color = color
        self.model = model
        def printDetails(self):
        print(self.make+" "+self.color+" "+self.model)
        class Car(Vehicle):
        def __init__(self, make, color, model, bodyStyle):
        Vehicle.__init__(self, make, color, model)
        self.bodyStyle = bodyStyle
        # different name with parent class
        def printCarDetails(self):
        self.printDetails()
        print(self.bodyStyle)
        car = Car("Honda", "Gray", "Sudan", "Cool Style")
        # Honda Gray Sudan
        # Cool Style
        car.printCarDetails()
  • Polymorphism

    • Definition

      A same object shows different forms and behaviors.

      It can be presented by extends keyword.

    • Illustration

      polymorphism-principle

    • Types

      Dynamic Polymorphism VS Static Polymorphism is also known as overloading vs overriding.

      • Dynamic Polymorphism

        It allows method can be defined with the same name, return type, and parameters in the parent class and child class.

        It is also known as runtime polymorphism by using overriding.

        // Java Example
        // See Java OOP Example
      • Static Polymorphism

        It is also known as compile time polymorphism by overloading method.

        class Calculator {
        int add(int num1, int num2) {
        return num1 + num2;
        }
        int add(int num1, int num2, int num3) {
        return num1 + num2 + num3;
        }
        public static void main(String args[]) {
        Calculator obj = new Calculator();
        System.out.println("10 + 20 = " + obj.add(10, 20));
        System.out.println("10 + 20 + 30 = " + obj.add(10, 20, 30));
        }
        }
    • Advantages

      • Method overloading allows methods that perform similar or closely related functions to be accessed through a common name.
      • Method overloading can be implemented on constructors allowing different ways to initialize objects of a class
      • Method overriding allows that the child classes can give their own specific implementations to inherited methods without modifying the parent class methods.
      • Method overriding allows that a child class can use the implementation in the parent class or make its own implementation
    • Example

      • Java OOP

        // base class
        class Shape {
        public double getArea() {
        return 0;
        }
        }
        // subclass 1
        class Rectangle extends Shape {
        private double width;
        private double heigh;
        public Rectangle(double width, double heigh) {
        this.width = width;
        this.heigh = heigh;
        }
        public double getArea() {
        return width * heigh;
        }
        }
        // subclass 2
        class Circle extends Shape {
        // Private data member
        private double radius;
        // Constructor
        public Circle(double radius) {
        this.radius = radius;
        }
        // Public method to calculate Area
        public double getArea() {
        return 3.14 * radius * radius;
        }
        }
        class Main {
        public static void main(String[] args) {
        Shape rect = new Rectangle(3, 4);
        Shape circle = new Circle(4);
        System.out.println(rect.getArea()); // 12.0
        System.out.println(circle.getArea()); // 50.24
        }
        }
      • Python OOP

        class Shape:
        def __init__(self):
        self.sides = 0;
        def getArea(self):
        pass
        class Rectangle(Shape):
        def __init__(self, width, height):
        self.width = width
        self.height = height
        self.sides = 4
        def getArea(self):
        print("Rectangle:",self.width*self.height)
        class Circle(Shape):
        def __init__(self, radius):
        self.radius = radius
        self.sides = 1
        def getArea(self):
        print("Circle:", 3.14 * self.radius * self.radius)
        rect = Rectangle(3,4)
        circle = Circle(4)
        # Rectangle: 12
        rect.getArea()
        # Circle: 50.24
        circle.getArea()
  • Abstract

    • Definition

      It shows only the essential features of an object to the user and hides the inner details to reduce complexity.

    • Illustration

      abstract-principle

    • How

      How to achieve abstraction?

      Anstract class and Interface.

    • Advantages

      It can reduce code complexity.

    • Example

      • Java OOP

        // Abstract class
        public abstract class Animal {
        public abstract void makeSound();
        public void move() {
        System.out.println(getClass().getSimpleName()+" is moving");
        }
        }
        class Dog extends Animal {
        @Override
        public void makeSound() {
        System.out.println("Woof Woof....");
        }
        }
        class Cat extends Animal {
        @Override
        public void makeSound() {
        System.out.println("Meow Meow....");
        }
        }
        class Main {
        public static void main(String[] args){
        Animal dog = new Dog();
        Animal cat = new Cat();
        // Dog is moving
        dog.move();
        // Cat is moving
        cat.move();
        // Woof Woof....
        dog.makeSound();
        // Meow Meow....
        cat.makeSound();
        }
        }
        // Interface
      • Python OOP

        from abc import ABC, abstractmethod
        class Shape(ABC):
        @abstractmethod
        def area(self):
        pass
        @abstractmethod
        def perimeter(self):
        pass
        class Square(Shape):
        def __init__(self, length):
        self.length = length
        def area(self):
        print(self.length * self.length)
        def perimeter(self):
        print(4 * self.length)
        square = Square(2)
        # 4
        square.area()
        # 8
        square.perimeter()