This content originally appeared on Level Up Coding - Medium and was authored by BenMauss
Using D&D to Understand the Four Pillars of OOP, Part IV

So far, we’ve covered three out of the four Pillars of Object-Oriented Programming: Inheritance, Abstraction, and Polymorphism. Today, we’ll be wrapping this series up with the final pillar: Encapsulation (and no, I did not plan the series out to set up that pun; It’s just a happy accident). But first, a brief recap!
Inheritance
If you remember, Inheritance is the ability of a class with hierarchal relationship (Parent-Child classes) to pass on data, variables, and methods to their subclasses. If Animal class has a method called speak(), then any child class of Animal (such as Fox) will inherit that method.
Abstraction
This is the ability for the developer to hide source code and only provide the user with the details needed to use the methods and data stored in the classes and packages. This is great for both the developer and the user. The developer can protect their source code and the user doesn’t need to write out complex code for themselves to perform a function. If you’ve ever used the pd.read_csv() method from the Pandas library to convert a .csv file to a dataframe, then you’ve benefitted from the power of Abstraction. You don’t need to know all of the underlying code and processes. You just need to know what method to call and the arguments to pass. Meanwhile, Pandas can protect their intellectual property.
Polymorphism
I gotta make a shout-out to Angelo Hulshout for providing me with a much better definition for Polymorphism. Last time, I made the mistake of saying that Polymorphism allowed classes to share the same name but serve “different purposes”. While this is technically possible, it’s a terrible idea. Consider the following situation:

Here, we made the Animal class with the speak() method. Fox class is a child of the Animal class, because a fox IS-AN animal. The Fox class will initialize all Fox objects in a “hungry” state. Then, we decided to use method overriding to repurpose the speak() method (which it inherited from the parent Animal class) so that it ‘feeds’ our fox and changes the hunger state.
As you can see, the code still works, but it’s also very dumb and illogical. Why not make a feed() method instead? We could have provided an implementation of the speak() so that it printed out sounds that are unique to the fox, but no! We chose poorly and now must reap the consequences of our foolishness.
Anyway, Angelo pointed this problem out to me and provided a better definition:
Polymorphism allows different implementations of the same functionality.
In other words, classes can provide different implementations for a method to achieve the same functionality. Thus, the speak() method can be implemented differently between the Animal and Fox classes, but they still serve the same function: make the object “speak”.

And yes, there is more to Polymorphism than just method overriding, such as upcasting/downcasting classes and method overloading, but let’s allow this to suffice for our review.
Time to move on to Encapsulation!
Encapsulation
Encapsulation is the wrapping together of data and methods within a unit or class. This restricts direct manipulation of variables and data to prevent accidental modification. Let’s pull up our example of the Dragon Turtle.



So Sentient is an abstract ancestor class from which Monster is derived. Monster is also abstract because it doesn’t provide an implementation for the inherited abstract method, calculate_hit_points(). DragonTurtle is a child of the Monster class (thus, a grand-child to Sentient). It provides an implementation for calculate_hit_points(), and is, therefore, a concrete class.
As you can see, the DragonTurtle class also provides default stats define all Dragon Turtle objects on instantiation. You’ll notice that in the initializer that the hit_points are initialized by calling the calculate_hit_points() method. This makes it so that the Dungeon Master (DM) doesn’t need to run the method after creating the object.
We do have an issue, however. Currently, all of the methods, variables, and their associated data are “public”. This means that any class (and I mean ANY) can access and modify them. That’s how vulnerable the data is.
So how do we restrict access? Well, we can either make our data protected or private.
What’s the Difference?
Generally speaking, protected methods and data can be accessed by any subclass, as well as any class within the same package. Take note of how I said that ANY subclass can access this data. This includes subclasses that are located in a different package. As long as they’re in the “family tree”, they can access the data.
(Again) Generally speaking, private methods and data can only be accessed from within the same class (or through Python name mangling, but don’t worry about that right now). Subclasses do not have access to these data.
Note: In Python, there is no such thing as a private instance variable that can only be accessed inside the object. Instead, certain conventions have been generally implemented to achieve the same goal.
So which one should we choose? Well, we do have hierarchal relationships between our three classes here, but at the same time, we don’t want anyone to change data associated with the variables. So let’s make our methods protected, and our data private. In Python, to make variables and methods protected you simply prefix them with a single underscore (e.g. self._hit_points). To make them private, you prefix them with two underscores (e.g. self.__hit_points). Let’s go ahead and do this to our Sentient class.

We’ll do the same with Monster.

With that out of the way, let’s think about our DragonTurtle class. This a concrete class capable of creating objects. We want users to be able to interact with these objects. What good is it to a DM if they can make 50 different Dragon Turtles to attack a small whaling boat filled with their players if they can’t access and retrieve any of the data associated with them? Because of this, we make public “getter” and “setter” methods so that the user can interact with the object indirectly. We’ll do this with the DragonTurtle class by making a getter and setter method for hit_points.

As you can see, our getter method get_hp() simply returns the value of the private variable. This extra degree of distance between the variable and the user/developer prevents any accidental modifications.
You may be wondering why I included a setter method for the hit-points if those are calculated via the method. Well, this is more for the sake of the DM. Say there is a player in your campaign who is just way too strong and is breaking the game. You want to create an encounter that is challenging, but not impossible for the rest of the group, while also actively trying to make sure that you can destroy that player’s character and bring balance to the campaign. The set_hp() method allows for a more “homebrew” approach.
Let’s test these methods out!

Our getter and setter both work great! Now at the bottom, you’ll noticed that we retrieved the hit-point value without using our getter method. Instead, we used Python name mangling. This is a way of circumventing the getters and setters. As you can see, you still can’t change the values without taking deliberate steps (No one accidently types x._DragonTurtle__hit_points).
Summary
Encapsulation is a way of hiding variables, data, and methods and protect them from accidental modification. While Python doesn’t have conventional means of creating private instance variables like C++ and Java, simple practices were adopted to help create the same effect.
With that we’ve come to the end of our discussion of the Four Pillars of OOP! There is a certain unity within these four concepts that make it so that missing one will cause the foundation of the language to collapse. They all work in symbiotic relationship, each benefitting from the other. It’s quite remarkable!
OOP and D&D: Encapsulation was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by BenMauss

BenMauss | Sciencx (2021-04-14T17:32:55+00:00) OOP and D&D: Encapsulation. Retrieved from https://www.scien.cx/2021/04/14/oop-and-dd-encapsulation/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.