cover image

Abstract Class

Of course, modern developers already have at least a basic understanding of how Object-Oriented Programming (OOP) paradigm can be implemented in a language that they understand or use the most, but conceptually, OOP can be very confusing to understand. If you have not studied the concept isolated from the vices of a programming language, then you are probably repeating things that you have learned by copying without actually understanding the design of OOP. Quite often, I have seen big projects written in an OOP language without taking advantage of inheritance. I even had to explain to a developer that a Superclass is not a class that is very large! Well, this concern led me to write this article.

Earth and Basketball

Both of them are round, well, at least for those intelligent enough to understand that the Earth is not flat. Round is a property that they share with each other. We can also say that a marble ball shares the same property because it's also a sphere, and we can wonder about The Blue Marble in which life as we know it takes place. But one thing is certain, despite the fact that they share a common property, they are very different objects! With this simple paragraph, we have taken a trip into the concepts of OOP without even noticing it! I will explain it!

Objects

Every entity in the physical or abstract world is an object. The basketball and the Earth are both objects of the physical world, and each of them can be identified and manipulated. We can also define abstract objects such as a person's name or a mathematical equation, which can also be recognized or manipulated. Each of these objects is different from each other, although we can classify them by analyzing their properties, much like we did with the Earth, the basketball, and the marble.

Objects might be different, but they can be part of the same class. For instance, the Earth, the basketball, and the marble can be classified as 'spheres', which means that they are instances of spheres. A sphere is rounded, but it can also roll, which is an action, a method that all spheres have in common. We can classify certain objects as being part of the same group, being instances of the same class.

Classes

So, a class in the real world is a collection or group of objects that have certain attributes or traits in common, as mentioned above. However, in OOP, a class is also a blueprint that produces objects. In the context of OOP, objects are instances of classes, which means that every property or method that a class has defined will be available for the object. Let's take an object to work on, such as the basketball. Can you list the properties and methods (actions) that a basketball has? Let's take a look!

  • Properties
    • Color
    • Stripes
    • Form
    • Weight
  • Methods (actions)
    • Roll
    • Bounce

Okay, maybe you've found more characteristics of a basketball than I have, and that's fine. The important thing is that you're thinking of a class of objects. In OOP, we define properties as variables inside the class definition and their methods as functions. Let's take a look at how we should implement this class in Python:

class Basketball:
    def __init__(self, form, weight, stripes, color):
        self.form = form
        self.weight = weight
        self.stripes = stripes
        self.color = color
        
    def roll(self):
        print(f"Rolling the {self.form}...")
        
    def bounce(self):
        print(f"Bouncing the {self.form}...")

The class as we said before, is just the definition, a blueprint to produce objects. If we want to create a new object of the class Basketball, then we have to create an instance of this class:

new_basketball_obj = Basketball(form="ball", weight=1, stripes=True, color="orange")

And that's it! We've just created an object stored in the new_basketball_obj variable. We can access its methods and attributes by using the dot notation:

my_basketball_obj.color()
# returns 'orange'

my_basketball_obj.roll()
# prints 'Rolling the ball'

my_basketball_obj.bounce()
# prints 'Bouncing the ball'

Sharing

So far, so good. We've explained a lot about objects and classes, but since we are just scratching the surface of OOP, we have not yet mentioned any advantages to using this paradigm. One major advantage is that objects can share properties and methods, and their classes can have shared attributes. If we think critically, we'll be able to identify that the classes for a basketball, a marble, and the Earth objects will contain some methods and properties in common because all of them are spheres.

Abstract Classes & Inheritance

If we find properties and methods that many different objects can share, we should start thinking about how to define them in their classes. But before we can do that, we need to ask ourselves the main question: What do the basketball, the Earth, and the marble have in common? Before continuing with the reading, take a moment to think about this question: what do the basketball, the Earth, and the marble have in common? The answer is that all of these objects share some similarities because they are all spheres!

This is an abstract concept, and if you think of a sphere as an object, your interpretation may differ from mine. Additionally, you may not be able to conceive of a sphere without some sort of referential, such as a ball. Spheres are abstract entities, and we cannot create an object from this concept alone; we need some referential. Similarly, cats, dogs, and sharks are all animals and share many characteristics, but we cannot conceive of an animal without some sort of reference point.

Basketballs, the Earth, and marbles are all spheres, and a sphere is an abstract entity. Abstract entities cannot have objects without a referential, but they help us identify and share properties with similar objects. In OOP, we can define abstract classes to specify properties and methods that concrete classes can inherit from. We have answered the last question, "What do basketballs, the Earth, and marbles share in common?" They are all spheres. So, the next question we should ask ourselves is, "How do we define a sphere as an abstract class?" Here's an example using Python:

import abc

class Sphere(metaclass=abc.ABCMeta):
    
    @abc.abstractproperty
    def form(self):
        pass
    
    @abc.abstractproperty
    def color(self):
        pass
    
    @abc.abstractproperty
    def weight(self):
        pass
    
    @abc.abstractmethod
    def roll(self):
        pass

In Python, we define an abstract class using the abc library, but other OOP languages like Java use the abstract keyword. The key feature of abstract classes across all OOP languages is that the properties and methods are not implemented within the class definition itself. As we saw in the previous example, all of the methods and properties were defined using the pass keyword, which tells the Python interpreter to skip the implementation of each attribute while still keeping it defined within the class.

The abstract class serves as a guide for other classes where its properties and methods are meant to be inherited. Different OOP languages have their own ways to define abstract classes. In Python, we use the abc library, while in Java, we use the abstract keyword. However, all OOP languages share the same concept that properties and methods of an abstract class are not implemented in their own scope. As we can see in the example above, all the methods and properties of the Sphere class are defined using the pass keyword, which tells the Python interpreter to skip the closure definition of each attribute while keeping them defined in the class.

from .superclasses import Sphere

class Basketball(Sphere):
    def __init__(self, form, color, weight):
        self._form = form
        self._color = color
        self._weight = weight
        
    @property
    def form(self):
        return self._form
    
    @property
    def color(self):
        return self._color
    
    @property
    def weight(self):
        return self._weight
    
    def roll(self):
        print("Basketball is rolling...")

In Python, the inheritance relationship between classes is defined by placing the name of the parent class in parentheses after the name of the child class, separated by a comma. So, in the example above, we can say that the Basketball class inherits from the Sphere class.

Abstract class in actual projects

Well, thinking of an MVC structure, the Model, View, and Controller entities can be implemented as abstract classes where each one of them will implement and share specific properties and methods that the developer should be aware of. Their objects might be different, but they should be identified as an entity of a Model or a Controller, just like a cat is identified as an animal. This avoids code redundancy and complexity. For instance, imagine that a developer has defined a class named Controller in a project that you are working on, but actually, that class is not a controller at all. Instead of a controller, it is something more similar to a Model, but the developer thinks that calling it a Controller was much clearer because he was "controlling" how data would be stored in the database. If that class had been inherited from Model, then the situation would be much clearer to understand.

References

https://dl.acm.org/doi/pdf/10.1145/947955.947961

April 30, 2023

marcelfox.com | 2025