DEV Community

Cover image for object-orientated programming - an intro.

object-orientated programming - an intro.

Hi fam and welcome back to another blog.

Recently I was in a situation where I needed to describe some OOP fundamentals, and it had been so long that I'd actually coded strictly in OOP that I decided it was time for a refresher.

Bare with me, the code examples I use will be templates and I've deliberately chosen to leave the methods empty, so use your imagination we should be able to work out what they return by the naming conventions 😇.

Functional programming

So for comparison, what is OOP up against? That would primarily be functional programming.

Functional programming is defined by two definitions

  1. It's deterministic: it will return the same result given the same arguments.
  2. It doesn't cause any observable side effects, ie modifying a global object passed by reference.

I won't go too deep here as we're discussing OOP and just wanted to give a comparison, but this is a topic I will probably discuss at a later date.


What is OOP?

OOP is a programming design model designed around objects, which themselves contain their own data in the form of fields and methods to operate the functions on that data.

Most commonly OOP is arranged around Classes that create instances of objects to interact with other classes.

So where functional programming can be considered smaller contained programs that return different results given data, OOP is an object that represents the stuff it and contains its own data structures, operating rules and mutates its own state/data.

The big 4

While different OOP languages do mention more, there are 4 main principles of OOP, encapsulation, abstraction, inheritance and polymorphism

Let's dive straight into it with encapsulation and a little bit of code!

Encapsulation

Wikipedia states that encapsulation is the bundling of data within the methods that operate on that data, meaning encapsulation is a nice way of controlling the data within a class to external objects.

From within the class, we can use Getters and Setters to set the rules of what fields can be viewed/accessed and what data (if any) can be modified.

Encapsulation adds security to the code itself and allows us to define what we want to be available and to what.

Let's look at some code

class Teacher {
    // Declare protected (private) fields
    _attendance = 0;

    constructor(name, birthday, subjects, grades) {
        this.name = name;
        this.birthday = birthday;
        this.subjects = subjects;
        this.grades = grades;
    }

    get showGrades() {
        // Getter
        return this.calcGrades();
    }

    set showGrades(grades) {
        // Calculate grades formula
        return result;
    }

    rollCall() {
        return console.log("Roll Call!");
    }

    updateAttendance() {
        // add a day to the attendance days
        this._attendance++;
    }
}

const teacherOne = new Teacher("Cooper", "01/01/1984");
teacherOne.showGrades();
Enter fullscreen mode Exit fullscreen mode

In this example, showGrades() is prefaced with get, and the get is calling set showGrades(grades) where all the work is being performed.

This is extended upon in Abstraction.


Abstraction

Abstraction shares similarities with Encapsulation, in an attempt to alleviate large unwieldy codebases and to improve maintainability, Abstraction is splitting large objects down into much smaller ones.

For example, a car, when we start a vehicle we use the key, as we turn the key and the motor starts, all the inner operations of why that car starts are abstracted away behind the key turn object.

We don't need to know all the inner workings of why the car started, it just did.


Inheritance

Inheritance is a way to reuse objects and cut down on excess code when two objects share features.

Take our Teacher and Student object for example, and while they have differences like date-of-birth, grades, etc, a Student has grades and a subjects field but a teacher wouldn't (or not in the same capacity, but more on that later).

Well, Inheritance would be a swift way to incorporate all the shared fields from Teacher without having to duplicate everything.

Let's look at some code

class Teacher {
    // Declare protected (private) fields
    _attendance = 0;

    constructor(name, birthday, subjects, grades) {
        this.name = name;
        this.birthday = birthday;
        this.subjects = subjects;
        this.grades = grades;
    }

    get showGrades() {
        // Getter
        return this.calcGrades();
    }

    set showGrades(grades) {
        // Calculate grades formula
        return result;
    }

    rollCall() {
        return console.log("Roll Call!");
    }

    updateAttendance() {
        // add a day to the attendance days
        this._attendance++;
    }
}

// Child class Student, inherits from parent Teacher
class Student extends Teacher {
    constructor(name, birthday, subjects) {
        super(name, birthday, subjects);
    }

    skipClass() {
        // additional method for Student child class
        return console.log("I missed the bus");
    }
}
const studentOne = new Student("Cooper", "01/01/1984");
studentOne.rollCall();
Enter fullscreen mode Exit fullscreen mode

As we can see from the example, Student doesn't contain rollCall, but as Student class inherited from the parent Teacher class, we can create an instance of Student and call the roleCall method.

TaDaa sweet huh


Polymorphism

Probably the most complex of them all, but let's break it down.

Polymorphism is the ability of an object to take many forms, or in a more readable term, it allows us to use a class like its parent so there are no mixups with data types, and each child class can implement its own version of the method.

For example, our Teacher class has grades, and our Student class also inherits grades, but the student calculation of grades would be different from how a teacher would calculate grades, this is where Polymorphism comes in.

Polymorphism means we can create different methods for the derived classes, and through Inheritance, objects can override the shared parent method with child-specific behaviors.

Using rollCall as a code example

class Teacher {
    // Declare protected (private) fields
    _attendance = 0;

    constructor(name, birthday, subjects, grades) {
        this.name = name;
        this.birthday = birthday;
        this.subjects = subjects;
        this.grades = grades;
    }

    rollCall() {
        console.log("Roll Call!");
    }

    updateAttendance() {
        // add a day to the attendance days
        this._attendance++;
    }
}

// Child class Student, inherits from parent Teacher
class Student extends Teacher {
    constructor(name, birthday, subjects) {
        super(name, birthday, subjects, grades);
    }

    rollCall() {
        console.log("Here, teacher.");
    }
}

const studentOne = new Student("Cooper", "01/01/1984");
studentOne.rollCall() => Here, teacher.
Enter fullscreen mode Exit fullscreen mode

In our example, both the Teacher and Student use the rollCall() method, but it would require different outcomes, a teacher would call for attendance and a student would reply.

Polymorphism means that we can inherit a method from a parent class but also change it to suit our needs.

This is one of those awesome rabbit hole moments that I could potentially do down for days, but hopefully, you get the idea.


Well, I hope you enjoyed this recap on OOP as much as I did, if there are any further things you'd like to point out feel free to let me know.

I am a big fan of constructive feedback as I start to blog more and more.

Peace out!
Coops

Top comments (0)