Understanding relations

It depends on the use case.

If your scenario is creating a flexible template for the Type which is prone to modification afterwards, I guess a simple class inheritance is a suitable analogy.

If your scenario is forcing a type to follow a template (instead of using the template as just a default starting point), in OOP, there is a design pattern called template method (yeah the same name). In template method, a template class is first developed as a blueprint for other classes.

For example,

from abc import ABC, abstractmethod

class AbstractClass(ABC):
    """ 
    A template for a general workflow, with specific steps left to be defined by subclasses. 
    """

    def template_method(self):
        """Template method that defines the algorithm's skeleton."""
        self.step_one()
        self.step_two()
        self.step_three()


    def step_one(self):
        """Concrete step."""

        print("Step 1: Common behavior")

    @abstractmethod
    def step_two(self):
        """Abstract step that must be implemented by subclasses."""
        pass

    def step_three(self):
        """Concrete step."""
        print("Step 3: Common behavior")


class ConcreteClass(AbstractClass):
    """Subclass implementing the abstract method."""

    def step_two(self):
        """Implementation of the abstract step."""
        print("Step 2: Subclass-specific behavior")


# Example usage:
obj = ConcreteClass()
obj.template_method()

In this pattern:

  • The template_method() provides the overall structure of the process.
  • Some steps, like step_two(), are abstract and must be provided by subclasses.
  • Other steps, like step_one() and step_three(), have default implementations but can still be overridden if needed.