Search code examples
pythonabc

Is it OK to define optional methods on abstract base class?


Is it a good practice to have non-abstract methods on abstract base classes? I mean, methods that can, but don't have to, be present on subclasses of particular ABC?

Technically it is possible, as seen in the below example (ConcreteDataProvider does not implement disconnect; it only has to implement connect):

from abc import ABC, abstractmethod

class AbstractDataProvider(ABC):
    @abstractmethod
    def connect(self):
        pass

    def disconnect(self):
        pass

class ConcreteDataProvider(AbstractDataProvider):
    def connect(self):
        pass


data_provider = ConcreteDataProvider()

Solution

  • It is fine to have ABC with concrete methods to provide default implementations. The standard library has several such cases:

    • The example of using abc.ABCMeta provides a non-abstract method.

      The get_iterator() method is also part of the MyIterable abstract base class, but it does not have to be overridden in non-abstract derived classes.

    • The ABCs of the collections.abc module provide default methods (termed "Mixin Methods").

      ABC Inherits from Abstract Methods Mixin Methods
      ... ... ... ...
      Iterator Iterable __next__ __iter__
      Generator Iterator send, throw close, __iter__, __next__
      ... ... ... ...

    When "do nothing" is a sensible default, there is no problem with a concrete method having a default implementation that is just pass. This can especially be useful when you expect that many implementations will need this method: by providing a default, it is safe for client code to always call this method.


    Note: When the pattern is specifically connect/disconnect, open/close, or similar pairs of methods to be called before/after usage, the __enter__/__exit__ pair of a context manager is the appropriate interface.