My first foray into OOP
Tags: python, beginners, learning
Published: 2024-05-20 21:35:43

Okay, maybe it wasn't _really_ my first foray into OOP, but I don't think I'm going to count the couple pages of "Java: A Beginner's Guide" I read about a year ago. Or the one-off C++ class I ended up dropping after a few months because I was a Biology student and I really thought I had no business being in there. A comp sci minor was just not in the cards at that time. For the most part, I've stuck to my side of the road since I began my coding journey and learned as much JavaScript a beginner could before hopping into a bootcamp. It's where I began building my foundation and learning the fundamentals of what it is to think and breathe like a programmer. It's where I was most comfortable and where I was most confident. I breezed through the lessons, waded through a whole section of React, and learned that React was infinitely better. And, not to toot my own horn, I was pretty decent at it - at least according to my bootcamp requirements. I was feeling great. And then, I was hit with Python.

![Python indentation meme](https://miro.medium.com/v2/resize:fit:1000/0*FGz8gU3nQILSesYT.png)

The spaces, the indentations, the lack of curly brackets. I thought I was going to lose my mind. Reading Python was like reading a run-on sentence the length of a paragraph. Although the language syntax bore some resemblance to JavaScript, which I grew to love, I initially struggled to adjust. And after all that adjusting, I was faced with another, larger hurdle. Learning about and using Classes.

Python is an object-oriented programming language, as I'm sure most readers here already know. But if you're a beginner like me, it's not explicitly clear how this language differs to JavaScript at a glance. Is it because JavaScript _doesn't_ have objects? Then what was that data type I learned about encompassed in fancy curly brackets? Or is it because Python focuses on this aforementioned data type as its main data structure? Because Python is "object"-oriented, get it? I had a lot of questions and apprehension coming into this new language but I also wanted to keep an open-mind. So here's what I learned for the beginners in the back.

##Objects and Classes

A class is a code template to create objects in Python. It's made up of methods and variables and is used to support _inheritance_ by reducing redundant code. I'll touch on inheritance later on but all you have to know for now is that classes are extremely important in Python because we use them to create objects.

Everything in Python is an object. And I mean, _everything_. Integers, strings, floating point numbers, arrays and even dictionaries, are all objects that are built-in. Objects in Python are instances of a particular class that contain its own data and functions to manipulate that data, almost like its own mini-program. 

To create a class, we use the `class` keyword:

![Class keyword code block](https://i.postimg.cc/sgwbgJVq/Class-Keyword-1.png)

And to create an object, you call the class:
![Object create code block](https://i.postimg.cc/7ZsQkY9y/Create-Object.png)

Beyond objects and classes, a lot of people will also throw key terms to memorize at you when you first pick up an OOP language. Abstraction, Polymorphism, Encapsulation, and Inheritance. These concepts are vital to understanding why most major software development companies prefer OOP languages. And thankfully, the couple pages of "Java: A Beginner's Guide" that I read summarized what each term means in the scope of programming.

##Abstraction

Goal: Simplifying Complexity

Abstraction is the process of hiding the complex implementation details of a system and exposing only the necessary parts. It’s like driving a car; you don’t need to understand how the engine works to drive it. You only interact with the steering wheel, pedals, and dashboard.

In programming, abstraction allows you to define complex operations in simple terms. For example, let's take this car analogy further and consider a Car class in a program:

![Car class abstraction code block](https://i.postimg.cc/L4rb7fGj/Car-Class-Abstraction.png)

Here, `start_engine`, `drive`, and `stop_engine` are high-level methods that hide the intricate details of how a car starts, drives, and stops. This abstraction makes the Car class easier to use without requiring the user to understand its internal workings as users will only need to call the class along with its method. For example: `Car.start_engine()` and `Car.stop_engine()`.

##Inheritance

Goal: Reusing Code

Inheritance allows a class to inherit properties and methods from another class. This promotes reusing code and establishes a natural hierarchy between classes.

To continue with the car analogy: imagine you have a base class Vehicle and you want to create a Car class and a Bike class. Instead of rewriting common functionality, you can inherit them from Vehicle:

![Car class inheritance code block](https://i.postimg.cc/qMBHQ2KQ/Car-Class-Inheritance.png)

Here, Car and Bike inherit the `start` method and other properties from Vehicle, making the codebase more maintainable and DRY (Don't Repeat Yourself). In addition, we can utilize the `super` method to avoid even more redundancy.

![Super method code block](https://i.postimg.cc/y6mR43Nw/Super-Inheritance.png)

The `super` method returns a temporary object of the parent class and it's typically used to initialize parent class attributes or invoke parent class methods. In the example above, it is used to call the `__init__` method from the Vehicle class to make sure the `make` and `model` attributes are properly initialized without redundant code. This also allows the Vehicle class's `__init__` method to be modified without needing to also update its dependent classes.

##Encapsulation

Goal: Protecting Data

Encapsulation is all about bundling the data and methods that operate on the data into a single unit, i.e., a class, and restricting access to some of the object's components. This protects the integrity of the data and prevents unintended interference.

Let's use a new analogy and imagine a Store class. We could create many classes that inherit properties and methods from it but there is one class's data that we want to ensure the integrity of - the CashRegister Class. In the CashRegister class, we want to restrict direct access to the total balance:

![Cash register code block](https://i.postimg.cc/5yKY7LxG/Cash-Register-Encapsulation.png)

Above, `__balance` is a private attribute that can only be accessed with the class. The following methods `deposit`, `withdraw`, and `get_balance` provide controlled access to update and view the balance. This ensures the register's data integrity and prevents unintended interference.

##Polymorphism

Goal: Code Flexibility

![Polymorphism meme](https://miro.medium.com/v2/resize:fit:1000/1*sz41pRDSoadCXSvxRHvEiw.jpeg)

Polymorphism allows objects of different classes to be treated as objects of a common super class, something we've touched on throughout this blog. It enables one interface to be used for a general class of actions, making the code more flexible and easier to extend.

For example, consider an app that processes payments from different sources such as credit cards, PayPal, and Bitcoin. We can define a common interface in a superclass and implement specific details in the subclasses:

![Payment code block](https://i.postimg.cc/pTY1FX2y/Payment-Polymorphism.png)

In this example, `process_payment` is defined in the superclass Payment and implemented in each subclass. The `process_transaction` function can process any payment method, demonstrating polymorphism.

##Conclusion

Understanding objects and classes is vital to writing efficient, reusable, and simplified code. It is part of the core foundations needed to excel in Python and understanding other OOP languages. The principles of Abstraction, Inheritance, Encapsulation, and Polymorphism are equally essential for creating robust, flexible, and maintainable software. They enable developers to write code that is not only easier to understand but also easier to modify and extend. By mastering these concepts, even if you have to struggle through it like I did, you can leverage the full power of Object-Oriented Programming to build sophisticated and scalable applications. And at the end of the day, isn't that what we all want to achieve? I know this isn't a thick, well-researched, and well-written book like "Java: A Beginner's Guide", but I hope that this can help you in beginning your own Python journey.