Posted on

Table of Contents

This article is part of a series about tech interview. Go to Tech interview to read more.

⚠️ Since you are here I imagine that have a previous knowledge about programming, and programming language. If you don't know anything about this, maybe this article is not for you yet.

Object-oriented programming (OOP): an overview

Object-oriented Programming (OOP) is a programming paradigm that relies on concept of classes and objects (Nyakundi, 2022). Those concepts and the paradigms of OOP will be more explained in details.

Class vs Object

When we model a problem in terms of objects in OOP, we create abstract definitions representing the types of objects we want to have in our system (Mozilla, n.d.). Those abstract definitions is what we call a class.

Let's imagine that we will create a trading card game (TCG). To make that we need some rules, and those rules are shared between the game. One of those rules are the cards entity, like the example below:

public class Card {
    private final String name;
    private final String description;
    private final int attack;
    private final int defense;

    /*
        constructor and getters
    */

    /**
     * Check if this card is destroyed by the attacker.
     * 
     * @param Card attacker card
     */
    public boolean isDestroyedBy(@NotNull final Card card) {
        return card.getAttack() > this.defense;
    }
}

Ok, I know that the Card have those variables and methods. Know I need to instantiate with data from real world.

var knightOfKeyboard = new Card("Knight of Keyboard", "This programmer is a gentleman that always carry her own mechanical keyboard", 850, 900);
var pmOfChaos = new Card("Project Manager of Chaos", "Where this Project Manager go the place becomes a mess", 1200, 1000);

if (knightOfKeyboard.isDestroyedBy(pmOfChaos)) {
    System.out.println("Your card was destroyed");
} else {
    System.out.println("Your defense is better");
}

Those variables with the card is what we call an object.

TL;DR: Class is a template, containing variables and methods. Object is the instantiated class.

Paradigms of OOP

Now that you read about the difference between class and objects, it's also important to know some paradigms of OOP.

Inheritance

Our TCG is going on fire, but the players are talking that we have only character card. They are asking for another type. We will have know two types of cards: character card and app card. They share some variables and methods, but not all.

To make simple and don't repeat code, we will use one of the OOP paradigms, the inheritance.

abstract class Card {
    private final String name;
    private final String description;

    /*
        constructor and getters
    */
}

class CharCard extends Card {
    private final int attack;
    private final int defense;

    /*
        constructor and getters
    */

    /**
     * Check if this card is destroyed by the attacker.
     * 
     * @param Card attacker card
     */
    public boolean isDestroyedBy(@NotNull final Card card) {
        return card.getAttack() > this.defense;
    }
}

class AppCard extends Card {
    private final int modifier;

    /*
        constructor and getters
    */

    /**
     * Apply modifier at some character card.
     * 
     * @param Card card thaw will be modified
     */
    public void modify(@NotNull final Card card) {
        // TODO implement
        
    }
}

With the AppCard we can modify some information at the CharCard. Both of them is a Card.

We can say that Card is a superclass or parent class of both CharCard and AppCard. Also we can say that CharCard and AppCard are subclasses or child classes of Card.

We can shuffle both types at our deck, because both are subclasses of Card.

Encapsulation

This concept we are already using since the first example, let's see again:

abstract class Card {
    private final String name;
    private final String description;

    /*
        constructor and getters
    */
}

See, we let only the responsible for the data to manipulate that. Only Card have access to the data name. This is what this concept is about.

Encapsulation refers to the bundling of data and methods that operate on that data within a single unit (Geeks for Geeks, n.d.). We are hiding the implementations details, so the outside can't see how it works, but can interact with the data by methods.

Abstraction

The abstraction concept refers to the process of hiding the internal details, just describing things in simple terms.

We can take the List for example, we have some methods like add, but we don't know how it is implemented. We jus now that if we call this method sending some data as parameter, this data will be present at the list at the end.

Polymorphism

Polymorphism is the concept where an object behaves differently in different situations.

There are two ways to achieve that, by overriding, or overloading.

Difference between Override, and Overload

Override means that you will write a new behavior. Occurs on run-time.

To understand, let's go back to our card game, let's make a small change to the Card class, adding a toString method

abstract class Card {
    // ..

    public String toString() {
        return name;
    }

}

Yeap, nothing to drastic, but for the CharCard this is too shallow, we need more information. To make this, we will Override the toString method.

class CharCard extends Card {
    // ..

    public String toString() {
        return String.format("%s: %d/%d", name, attack, defense);
    }

}

Every call to toString from CharCard will have this new information, but the behavior of Card, or AppCard will be the same, since we didn't changed there.

But the overload is different, we can add new methods with the same name, but different parameters.

For example, we are able to create two different constructors and still valid. We can choose which one we want at different places.

class Deck {
    private final List<Card> cards;

    public Deck() {
        cards = new ArrayList<Card>;
    }

    public Deck(List<Card> cards) {
        this.cards = cards;
    }

    // getter
}

Also, the overload happens at compile-time.

TL;DR:

  • Override: Keep method signature, but change behavior
  • Overload: Two or more methods with same name, but different parameters

References