Object Oriented Programming/Abstraction
If you've ever made coffee using a coffee machine, you have probably experience abstraction. When you make your coffee, you make sure that there are ample coffee beans, you add water, add milk, and perhaps put in a fresh coffee filter. Then, you hit a button and a coffee of your choice is made. This is a good example of abstraction since the user doesn't need to be concerned about the right amount of milk needed for a specific type of coffee, or how many beans need to be ground up for the right amount, or what the temperature of the water needs to be, the user is only considered with providing the necessary materials to produce the final product. This same structure applies to object oriented programming. The user of the object should only be concerned with providing the necessary parameters for the final product and shouldn't really know or need to know how the object works internally.
Abstract classes and interfaces
In some languages it is possible to create a class which can’t be instantiated. That means that we can’t use this class directly to create an object – we can only inherit from the class, and use the subclasses to create objects.
Why would we want to do this? Sometimes we want to specify a set of properties that an object needs to have in order to be suitable for some task – for example, we may have written a function which expects one of its parameters to be an object with certain methods that our function will need to use. We can create a class which serves as a template for suitable objects by defining a list of methods that these objects must implement. This class is not intended to be instantiated because all our method definitions are empty – all the insides of the methods must be implemented in a subclass.
The abstract class is thus an interface definition – some languages also have a type of structure called an interface, which is very similar. We say that a class implements an interface if it inherits from the class which specifies that interface.
In Python we can’t prevent anyone from instantiating a class, but we can create something similar to an abstract class by using NotImplementedError inside our method definitions. For example, here are some “abstract” classes which can be used as templates for shapes:
class Shape2D: def area(self): raise NotImplementedError() class Shape3D: def volume(self): raise NotImplementedError()
Any two-dimensional shape has an area, and any three-dimensional shape has a volume. The formulae for working out area and volume differ depending on what shape we have, and objects for different shapes may have completely different attributes.
If an object inherits from 2DShape, it will gain that class’s default area method – but the default method raises an error which makes it clear to the user that a custom method must be defined in the child object:
class Square(Shape2D): def __init__(self, width): self.width = width def area(self): return self.width ** 2