DEV Community

Cover image for Level Up Your Object Oriented Programming Knowledge with Nintendo Switch 🎮👾
Juanda Martínez
Juanda Martínez Subscriber

Posted on • Edited on

Level Up Your Object Oriented Programming Knowledge with Nintendo Switch 🎮👾

Imagine for a moment that Object Oriented Programming (OOP) is like the inner workings of your favorite gaming console, the Nintendo Switch. Just as the Switch combines different components to bring your favorite games to life, OOP unites data and functions to create efficient and organized code. In this article, we'll embark on a journey to explore the four fundamental principles of OOP through the lens of the Nintendo Switch, will try my best to teach you this powerful programming paradigm with examples that are as enjoyable as a game of the great N. Get ready to level up your coding skills and game on as we unlock the secrets of OOP with the Nintendo Switch as our guide.

OOP relies on two major concepts: Classes and Objects. These concepts can be applied in code to enable us to build applications. Object Oriented Programming was created to guide the creation of better software, by achieving easier maintenance and reusability.

DISCLAIMER: The following examples are just an attempt to explain my point, there may be inconsistencies according to reality

CLASSES AND OBJECTS

Let's say that we want to create a brand new console, shall we? :) It comes in many colors, we have the ability to play videogames anywhere, it has a battery life of 6 hours that drains every time you play a game, and you can install many games on its internal storage! We decided to name it ✨Nintendo Switch

Nintendo Switch Lite Drawing

If we translate this in code, we can create a Class named NintendoSwitch and we list the principal attributes and its methods, think of a class as it were a template or blueprint that will specify how the console looks and the way it's going to perform some actions (I would like to explain this class/object stuff with Typescript first):

class NintendoSwitch {
  private color: string;
  private screenSize: number = 5.5;
  private storageCapacity: number = 8;
  private batteryLife: number = 6;
  private gamesInstalled: string[];

  constructor(color: string, gamesInstalled: string[]) {
    this.color = color;
    this.gamesInstalled = gamesInstalled;
  }

  playGame(game: string): void {/.code logic./}

  installGame(game: string): void {/.code logic./}

  checkBatteryLife(): void {/.code logic./}
}
Enter fullscreen mode Exit fullscreen mode

Here we have the principal attributes like color, screenSize, storageCapacity, batteryLife, gamesInstalled. Then we have the constructor, a function that serves to initialize the attribute's values when we create an instance of NintendoSwitch class.

Note that our class already has storageCapacity, batteryLife, and screenSize initialized, because it will be the same for all the new instances instead of color and gamesInstalled, those can be set at the moment we create the instance of the current class.

An Instance is equal to an Object, we create as many objects as we want from a Class, in most languages we use the new keyword in order to create a new object, every object can be different one from another, because we can have many NintendoSwitch objects with different colors and different games installed!

Instances example with Nintendo Switch Lite

In this case, none of our instances have games to play with :( but the good part is that you can now understand what Classes and Objects are, so let's move on!

In order to achieve mastery, we need to understand the ✨four principles of Object Oriented Programming✨ starting with the first one:

📦 ENCAPSULATION

Is the need to separate your code in independent pieces for a single purpose, think of it like a box 📦 that holds data (properties, attributes) and the things that can be done with that data (methods, functions). This way, you can ensure that your data is safe and it's used correctly.

This principle can define the reason for having classes, we encapsulate a set of attributes and the things we can perform with those attributes as methods, with the purpose of hiding the internal process and just showing what matters to the public, it's up to us if we want to set some attributes or methods as public, or keep it private just for internal use.

If you want to explain this in a more technical way:

Encapsulation is a way to restrict the direct access to some components of an object, so users cannot access state values for all of the variables of a particular object. Encapsulation can be used to hide both data members and data functions or methods associated with an instantiated class or object.

INHERITANCE

Is the idea that you can inherit perks and abilities from your parents 👨‍👩‍👦, like eye color or hair type.

Let's go back to the Nintendo Switch; Now we want to create a new console by taking all the things inside of the Nintendo Switch but with additional features. If we talk in terms of coding, maybe some newbie developer may think of copying and pasting the Nintendo Switch class and creating a new one to add the desired new features... easy, right? But what if I told you that instead of re-write the code again, we can create our new model from what we already have 😱 Yes! you heard it right! we can extend from the Nintendo Switch class and then create the Nintendo Switch Pro class without copying all the code from scratch, we will have all the features of the original Nintendo Switch, and then we can just add the new code for the features! on this new model, we want detachable controllers and also the ability to connect the Nintendo Switch to a dock and be able to play on a TV! how awesome is that?

So we proceed to create our new class for the Nintendo Switch Pro, extending from NintendoSwitch class, like this:

class NintendoSwitchPro extends NintendoSwitch {  
  constructor(props) {
    this.super(props);
  }

  detachJoycons() {/../}

  connectToTV() {/../}
}
Enter fullscreen mode Exit fullscreen mode

Nintendo Switch Drawing

We can see that its composition it's similar, but now we can detach the controllers (detachJoycons) to play with them wireless, and we can also connect it to the TV! (connectToTV)

Maybe this is a vague example but in the big picture this is ✨inheritance✨ we take the NintendoSwitch class, and extend this in a new class NintendoSwitchPro that inherits all the NintendoSwitch attributes and methods, and additionally we have two more methods that can do new things!

This approach makes things more organized and saves you from doing the same things over and over again.

POLYMORPHISM

Polymorphism means many shapes, in OOP we can modify the properties and methods that we inherited to have different behavior in a way that makes sense for each class. This makes our code flexible and easy to adapt to many use cases.

Going back to our previous example, our first class, Nintendo Switch, as we know has a little screen of 5.5in, its size makes you able to even fit in your pocket and the battery lasts 6 hours of continuous play! But then when we created the Nintendo Switch Pro, and decided that this new model would have a screen of 7in, bigger than his parent!! and Thus we have a larger size of the whole console that can barely fit in your jeans pocket, we increment the battery life up to 10 hours of continuous play, and the rest remains the same, so now our new class will end like this:

class NintendoSwitchPro extends NintendoSwitch {
  private screenSize: number = 7;
  private batteryLife: number = 10;

  constructor(props) {
    this.super(props);
  }

  detachJoycons() {/../}

  connectToTV(game: string) {/../}
}
Enter fullscreen mode Exit fullscreen mode

super() is another keyword that most languages adopt to refer to the super class or parent class, in the case above, we are using the same exact constructor of the parent class because we don't need to add anything new to it.

Explanation of inheritance with Nintendo Switch

As you can see, we set a couple of attributes that are named the same as some of the parent models but modified their values to fit the new necessity. This is called Overriding and it is a valid practice, even with methods! is like taking the inherited abilities and leveraging them with superpowers 💪🏻

ABSTRACTION

Abstraction means simplifying complex things by breaking them into smaller and more manageable parts. Think of it like driving a car 🚗 we don't need to know all the technical details of how the engine works, we just need to understand how the basic controls like the steering wheel, gas pedal, and breaks work. With that being said, our methods contained in the NintendoSwitch class can tell us WHAT it does, without caring much about HOW it does.

For example, the method checkBatteryLife() can tell us what it does just by its own name! but internally works like this:

// NintendoSwitch class file
checkBatteryLife(): void {
  console.log(`This Nintendo Switch has ${this.batteryLife} hours of battery life remaining.`);
}

//Our main script
const myFirstSwitch = new NintendoSwitch('Blue', []);

myFirstSwitch.checkBatteryLife(); // Console output: This Nintendo Switch has 6 hours of battery life remaining.
Enter fullscreen mode Exit fullscreen mode

As you can see, the batteryLife attribute on its own doesn't say much about it, it's just 6, but 6 what?? then checkBatteryLife() gives us more context, and the result is that the logged message in the console specifying that the battery life attribute is meant to be the hours left of battery life!

Sometimes we can find getters and setters functions inside classes, we won't focus on these things right now, but think of them as functions that help us to set/modify the value of an object's attribute (setters), and functions to read those values (getters). At first sight, this may seem useless, but sometimes this can keep our attributes safer, like by adding a validation layer, so no one can set a null-ish value that can break our app, or set that abstraction layer like in the example above to give a meaning to our attributes values.

In OOP we can hide complicated pieces of code and provide a simple interface, so we can focus on what our code does rather than how it does it, this makes our code easier to understand and maintain.


And that's all, folks!

I hope that you can understand better the OOP principles with these examples :) Let me know in the comments your thoughts, this is an important topic in software development, and can even get you an opportunity to get a job in a big tech company! they often opt for developers with this kind of general knowledge instead of looking for someone with a specific language, because if you know all of this stuff you are more likely to adapt to any technology.

This is the first of a three-part series that I'm about to write, because I want you to understand from my perspective, how OOP, Javascript Prototypes, and SOLID principles can be related ✨

Top comments (4)

Collapse
 
arafatweb profile image
Arafat Hossain Ar

Interesting way to learn about OOP.
Thanks.

Collapse
 
justaguyfrombr profile image
Misael Braga de Bitencourt

It is a good approach to use in classes.

Collapse
 
ithzavg profile image
Ithzamary

Amazing

Collapse
 
tempgmail profile image
TempGmail

Hey there, fellow tech enthusiast! Thanks for the intriguing comparison between Object Oriented Programming (OOP) and the Nintendo Switch. Your approach is not just informative but also a lot of fun. Let me dive into your excellent explanation of OOP's fundamental principles with a little story from my own experience.

Once upon a time in the world of software development, I found myself in a situation similar to the concept of encapsulation you mentioned. I was working on a complex project, and our team was tasked with creating a user management system for a web application. To ensure data security and reusability, we decided to create a class called "User" that encapsulated all the user-related data and functions. This class had private attributes like "username," "email," and "password," and methods to validate user data, update passwords, and handle user interactions.

The "User" class acted as a blueprint for creating individual user objects, much like your Nintendo Switch class. This way, we could have multiple user instances with different data, yet all adhering to the same structure and functionality. It made our code organized and secure, just as you explained. Whether it was a new user signing up or an existing user updating their details, we could rely on this "User" class to handle it all. It was a real game-changer for our project's development, and the encapsulation principle played a significant role in achieving this success.

Your storytelling method is fantastic for understanding these OOP principles. I'm looking forward to the next part of your series, especially the one about SOLID principles. Keep up the great work, and I'm sure your insights will help many aspiring programmers level up their coding skills and game on in the world of software development!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.