Using the __subclasshook__() method

We can define abstract base classes with complex rules for overrides to create concrete subclasses. This is done by implementing the __subclasshook__() method of the abstract base class, as shown in the following code:

class AbstractBettingStrategy2(ABC):

@abstractmethod
def bet(self, hand: Hand) -> int:
return 1

@abstractmethod
def record_win(self, hand: Hand) -> None:
pass

@abstractmethod
def record_loss(self, hand: Hand) -> None:
pass

@classmethod
def __subclasshook__(cls, subclass: type) -> bool:
"""Validate the class definition is complete."""
if cls is AbstractBettingStrategy2:
has_bet = any(hasattr(B, "bet") for B in subclass.__mro__)
has_record_win = any(hasattr(B, "record_win") for B in subclass.__mro__)
has_record_loss = any(hasattr(B, "record_loss") for B in subclass.__mro__)
if has_bet and has_record_win and has_record_loss:
return True
return False

This class is an abstract base class, built by extension from the ABC superclass. As with the previous example, a number of @abstractmethod definitions are provided. Any subclass of this class would be like the previous examples of the AbstractBettingStrategy class.

When trying to build an instance of the subclass, the __subclasshook__() method is invoked to determine whether the object can be built. In this case, there are three individual checks: has_bet, has_record_win, and has_record_loss. If all three checks pass, then the function returns True to permit the object to be built; otherwise, the function returns False to prevent it building an instance of an incomplete concrete class.

Using __subclasshook__() permits nuanced decision making with regard to the validity of a subclass of an abstract class. It can also lead to confusion because the obvious rule—that is, implement all @abstractmethod methods—isn't in use.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset