Abstract classes#
Abstract classes in Object Oriented Programming (OOP) are classes that cannot be instantiated.
In Python, abstract classes can be by inheriting the abc.ABC class. Abstract classes also need to have
abstract methods, otherwise Python will not treat the class as abstract. Trying to create an instance (object)
from an abstract class results in a TypeError exception.
from abc import ABC, abstractmethod
class MyAbstractClass(ABC):
@abstractmethod
def some_method(self):
pass
class MyClass(MyAbstractClass):
def some_method(self):
return 5 * 5
# OK
my_instance = MyClass()
# TypeError: Can't instantiate abstract class MyClass with abstract method some_method
my_abstract_instance = MyAbstractClass()
Let’s modify our example from Polymorphism.
1from abc import ABC, abstractmethod
2
3import tkinter as tk
4import tkinter.ttk as ttk
5import tkclasswiz as wiz
6
7# An abstract class
8class Wheel(ABC):
9 def __init__(self, diameter: float):
10 self.diameter = diameter
11
12 @abstractmethod
13 def get_info(self) -> str:
14 pass
15
16class WinterWheel(Wheel):
17 def get_info(self) -> str:
18 return "Wheel for winter."
19
20class SummerWheel(Wheel):
21 def get_info(self) -> str:
22 return "Wheel for summer."
23
24
25class Car:
26 def __init__(self, name: str, speed: float, wheels: list[Wheel]):
27 self.name = name
28 self.speed = speed
29 self.wheels = wheels
30
31 if speed > 50_000:
32 raise ValueError("Car can go up to 50 000 km / h")
33
34 if len(wheels) != 4:
35 raise ValueError("The car must have 4 wheels!")
36
37# Tkinter main window
38root = tk.Tk("Test")
39
40# Modified tkinter Combobox that will store actual objects instead of strings
41combo = wiz.ComboBoxObjects(root)
42combo.pack(fill=tk.X, padx=5)
43
44def make_car(old = None):
45 """
46 Function for opening a window either in new definition mode (old = None) or
47 edit mode (old != None)
48 """
49 assert old is None or isinstance(old, wiz.ObjectInfo)
50
51 window = wiz.ObjectEditWindow() # The object definition window / wizard
52 window.open_object_edit_frame(Car, combo, old_data=old) # Open the actual frame
53
54def print_defined():
55 data = combo.get()
56 data = wiz.convert_to_objects(data) # Convert any abstract ObjectInfo objects into actual Python objects
57 print(f"Object: {data}; Type: {type(data)}",) # Print the object and it's datatype
58
59
60# Main GUI structure
61ttk.Button(text="Define Car", command=make_car).pack()
62ttk.Button(text="Edit Car", command=lambda: make_car(combo.get())).pack()
63ttk.Button(text="Print defined", command=print_defined).pack()
64root.mainloop()
We can see that the Wheel is now an abstract class.
It is then inherited by WinterWheel and SummerWheel.
If we try to define the wheels parameter of our Car object, only these two inherited classes
will be definable.
We can see that while WinterWheel and SummerWheel are definable (due to Polymorphism),
Wheel is not.