Chapter 2: Polymorphism

Abstract methods

face Josiah Wang

We can take this idea of polymorphism further.

Your classes can sometimes be quite abstract. For example, you can have an Animal, a Building, a Device, a Toy etc. The problem is that sometimes you just cannot implement a method for such classes. For example, how does an Animal run()? How do you turn_on() something abstract like a Device, since different devices operate quite differently?

Such classes are called abstract classes. Abstract classes have at least one abstract method. For example, an abstract Device class might define an abstract method turn_on(), but does not tell you how it works. You just cannot turn on something as high-level as a Device! You just know that a Device is something that can be turned on. And Device might even use the turn_on() method in one of its methods (since that method knows that you can turn_on() a Device, even if it does not know how).

Because of this, you should NOT create an instance of an abstract class (i.e. device = Device()), because you will have a problem when you try to turn on the abstract device! You should instead design a more concrete subclass like Computer or Radio which will implement the turn_on() method. Then you can turn on this more ‘concrete’ device!

Below is a simple example. Device does not tell its subclasses how to turn_off(). It only specifies that they must implement their own turn_off() method, because all devices must be able to be turned off somehow. The DeviceController assumes that all devices should have a turn_off() method implemented (Line 29).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Device:
    def __init__(self, name):
        self.name = name

    def turn_off(self):
        raise NotImplementedError("Subclass must implement abstract method")


class Computer(Device):
    def turn_off(self):
        print("Shutting down all programs...")
        print("Logging out users...")
        print("Disconnecting external devices...")
        print("Shutting down operating system...")
        print("Sending shutdown signal...")
        print("Computer is turned off.")


class Radio(Device):
    def turn_off(self):
        print("Turning off the radio. Done!")


class DeviceController:
    def __init__(self, device):
        self.device = device

    def disconnect_device(self):
        self.device.turn_off()


computer = Computer("Dell XPS")
controller = DeviceController(computer) 
controller.disconnect_device()

If you try to pass an instance of Device to DeviceController, and try to disconnect a device, you will get a NotImplementedError.

1
2
3
device = Device()
controller = DeviceController(device) 
controller.disconnect_device() # NotImplementedError