Object Oriented Design

Inheritance

Python has inheritance:

from dataclasses import dataclass
from math import pi

@dataclass
class Shape:
    name: str

    def area(self):
        pass


@dataclass
class Rectangle(Shape):
    length: int
    width: int

    @property
    def area(self):
        return self.length * self.width

@dataclass
class Circle(Shape):
  radius: float

  @property
  def area(self):
    return self.radius ** pi

rect = Rectangle("Rectangle", 5, 10)
print(f"{rect=}")
print(f"{rect.area}")

circle = Circle("Circle", 5)
print(f"{circle}")
print(f"{circle.area}")

Interfaces

Let’s extend this with interfaces:

Let’s create virtual interfaces like we might in C++:

from dataclasses import dataclass
from abc import abstractmethod, ABC

@dataclass
class Shape(ABC):
    name: str

    @abstractmethod
    def area(self):
        raise NotImplementedError

# Does not define area method
@dataclass
class Rectangle(Shape):
    length: int
    width: int

rect = Rectangle("Rectangle", 5, 10)
print(f"{rect=}")
print(f"{rect.area()}") # Raises NotImplementedError

Mixins

Mixins can be used in an includes fashion here:

from dataclasses import dataclass

class Rectangle:
    length: int
    width: int

    def area(self):
        return self.length * self.width

class Square(Rectangle):
    def __init__(self, length):
        super().__init__(length, length)

class VolumeMixin:
    def volume(self):
        return self.area() * self.height

class Cube(VolumeMixin, Square):
    def __init__(self, length):
        super().__init__(length)
        self.height = length

    def face_area(self):
        return super().area()

    def surface_area(self):
        return super().area() * 6