OOP and D&D: Abstraction and Abstract Classes

Using D&D to Understand the Four Pillars of OOP, Part IIImage Source: RogueWatson.files.WordPress.comLast time, we spoke at length about the principle of Inheritance in Object-Oriented Programming. Inheritance is a trait in OOP languages that allow…


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 II

Image Source: RogueWatson.files.WordPress.com

Last time, we spoke at length about the principle of Inheritance in Object-Oriented Programming. Inheritance is a trait in OOP languages that allows a parent/superclass to pass down attributes, data, and methods to their child/subclasses. A major benefit of this is that developers can cut down on redundant code because they do not need to explicitly program a method over and over across many classes that have a hierarchal relationship (parent-child) since the child classes will have already inherited those methods and can pass them implicitly.

Inheritance also allows for method overriding, where a child class shares a method with its parent class, but implements it differently. Consider the following:

As you can see, thanks to Inheritance, Fox objects have access to their parent class’ speak() method implicitly. Foxes don’t make “generic animal noises”, however. As Ylvis once asked: What does the fox say?

The Fox class is still a child of the Animal class, and inherits the speak() method. However, the Fox class can provide its own implementation for the method, overriding it, so that it returns something that is more tailored to the subclass. This ability opens up the floodgates to Polymorphism, which we’ll discuss more next week. For now just know that Inheritance is a very important and powerful trait in OOP languages.

Today, we’re focusing on another Pillar of OOP: Abstraction.

What is Abstraction?

Abstraction is only exposing the user to the information that they need, and not to the underlying code that makes it all work. Last time, I mentioned that it’s similar to the process of turning on a car. The average driver will just say that you just need to “turn the key” or “push the button”. Any gear head will tell you that these are just a small part of what happens in the process, however. But does the average driver really NEED to know the whole process in order to start their car? Nope.

It’s the same with OOP. A developer can create packages filled with complex methods and code, but the user doesn’t need to know or see all of that. They only need to know how to use it.

Does Abstraction have anything to do with Abstract classes?

Nope!

So why are we talking about Abstract classes then??

Three reasons!

  1. Abstraction is a very easy concept to understand and doesn’t take a long time to explain. If you’ve ever imported Pandas and performed methods like pd.DataFrame.isna().sum().sum() (used to find the total number of NaN values in a dataframe) , you’ve experienced the benefits of Abstraction. It’s pretty great!
  2. If you’re like me and you learned concepts like Abstraction, Abstract classes, Interfaces, and about a dozen other subjects in such a frenzy that you scarcely remember anything that happened that weekend, you also might have had a synapse misfire and think that there’s a connection between the two.
  3. I need to redeem myself for a lapse in judgment when it came to my implementation of OOP to D&D mechanics.

You might remember last time, I made a big deal about how the dice roll is the most important behavior in D&D. We then made a class called DiceSet that creates a set of dice and had a method called ability_check.

I then stated that the ability_check is a behavior shared with all sentient beings in D&D (player characters, monsters, and non-player characters). This is why I chose to make our next class, Sentient, a child of DiceSet. That way the Sentient class would inherit the ability_check method.

There’s a problem with this logic, though, which I mentioned. The point of OOP is to represent real-world objects (or fictional ones in the case of D&D) in code. This means that Hierarchal relationships such as Parent-Child classes should makes sense. However, a Sentient object is NOT a DiceSet. So what went wrong? I got so wrapped up in the game mechanics and inheritance that I didn’t consider the relationship between the objects.

At this point, I have to give a shout out to Florian Salihovic again. Not only bringing this problem to my attention, but also for his excellent article where he tackles this problem with his own approach. I highly recommend reading it, as he does a fantastic job in showing how the relationships of objects and classes should dictate your design choices. This is shown in how he treats game mechanics and characters/NPCs (referred to as Agents in his article) as two separate entities. This makes perfect sense! Game mechanics are analogous to the Laws of Physics; they define what is and isn’t possible and all physical entities are subject to them. A player is not a rule (parent-child relationship), nor do they have a rule (this is composition, where you create an instance in a class that references another object). So, again, I highly recommend reading his article “Object-Oriented Dungeons & Dragons”.

So now that we know what I did wrong, let’s fix it! First thing we need to do is remove that reference to the DiceSet class.

Good, we fixed it! Now, you might notice something odd about this class. The default arguments are all left empty or None. Why is this? Well, we intentionally designed the Sentient class to be generic as possible so that we could make child classes that will be more specified to players, monsters, and NPCs. This way each of the child classes could provide their own implementation. Classes that are designed in this way are referred to as “Abstract Classes”. A formal definition is a class that contains one or more abstract methods (methods with no defined implementation). Their purpose is to provide a framework for other classes, while giving them the freedom to define methods that are tailored to their needs.

Since our Sentient class is pretty much an abstract class (it’s just missing the abstract methods to make it fit the formal definition) let’s go ahead and make it official. We’ll add an abstract method called calculate_hit_points to make sure that it fits the definition, but also so that this class is more than just a container for data.

In Python, to create an abstract class or method, you first need to import ABC (acronym for Abstract Base Class) and abstractmethod from the abc package. We declare our class as abstract with the class Sentient(ABC):. To make an abstract method, first declare it with @abstractmethod and name your method, passing self in as an argument. Leave the method empty with pass so that other classes can set their own implementations.

You might be wondering why there is a method for calculating hit-points if there is an attribute already listed in the Initializer. Well, let’s look at the entry here for a Dragon Turtle:

Notice how next to Hit Points it has 341, but also (22d20 + 110). This is a choice given to the Dungeon Master. They can either choose a default, median value of 341 hit points for all dragon turtles, or for a more diverse experience, each dragon turtle can have hit point values that are the sum of 22 rolls of a 20-sided die plus an additional 110 hit points. This would mean that you could have a “runt” with 132 (22*(1) + 110) hit points (the minimum) or a particularly beefy dragon turtle with 550 (22*(20) + 110) hit points (the maximum).

Let’s go ahead and make our Monster class:

You’ll notice that Monster also has a concrete method (it provides an implementation. Despite this, Monster is still abstract since it provides no implementation for the calculate_hit_points method. Children of abstract classes MUST provide implementation for ALL of the methods for them to become “concrete” and instantiable.

To that end, let’s make a class for Dragon Turtles.

Note: Normally, I would go through and make sure that every attribute was also filled in when we defined the DragonTurtle class, as these attributes are shared across all instances of DragonTurtle objects. However, to save time, I skipped this step, as the primary focus is the implementation of an abstract method.

Now that DragonTurtle has provided an implementation for the calculate_hit_points method, the class is considered concrete. We’ve even created a DragonTurtle named Bertha, and she has 378 hit points.

Why is This Important?

Just as how classes are a template for objects, abstract classes act as a template for other classes. When you want to provide a common interface for different implementations of a method, an abstract class is the way to go. They’re used to aid in the creation of APIs and Plugins for programs.

Join us next week for our discussion of Polymorphism!


OOP and D&D: Abstraction and Abstract Classes 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


Print Share Comment Cite Upload Translate Updates
APA

BenMauss | Sciencx (2021-03-30T17:53:23+00:00) OOP and D&D: Abstraction and Abstract Classes. Retrieved from https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/

MLA
" » OOP and D&D: Abstraction and Abstract Classes." BenMauss | Sciencx - Tuesday March 30, 2021, https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/
HARVARD
BenMauss | Sciencx Tuesday March 30, 2021 » OOP and D&D: Abstraction and Abstract Classes., viewed ,<https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/>
VANCOUVER
BenMauss | Sciencx - » OOP and D&D: Abstraction and Abstract Classes. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/
CHICAGO
" » OOP and D&D: Abstraction and Abstract Classes." BenMauss | Sciencx - Accessed . https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/
IEEE
" » OOP and D&D: Abstraction and Abstract Classes." BenMauss | Sciencx [Online]. Available: https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/. [Accessed: ]
rf:citation
» OOP and D&D: Abstraction and Abstract Classes | BenMauss | Sciencx | https://www.scien.cx/2021/03/30/oop-and-dd-abstraction-and-abstract-classes/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.