pythonpython-3.xabstract-classpython-2.xabstract-methods

Can't instantiate abstract class with abstract methods


I'm working on a kind of lib, and I'm getting an error.

Sorry couldn't just copy and paste it

I went on the basis that the code below works.

test.py:

import abc
import six

@six.add_metaclass(abc.ABCMeta)
class Base(object):

    @abc.abstractmethod
    def whatever(self,):
        raise NotImplementedError

class SubClass(Base):

    def __init__(self,):
    
        super(Base, self).__init__()
        self.whatever()

    def whatever(self,):
        print("whatever")

In the python shell:

>>> from test import *
>>> s = SubClass()
whatever

For my roster module, why am I getting this error:

Can't instantiate abstract class Player with abstract methods _Base__json_builder, _Base__xml_builder

Solution

  • Your issue comes because you have defined the abstract methods in your base abstract class with __ (double underscore) prepended. This causes python to do name mangling at the time of definition of the classes.

    The names of the function change from __json_builder to _Base__json_builder or __xml_builder to _Base__xml_builder . And this is the name you have to implement/overwrite in your subclass.

    To show this behavior in your example -

    >>> import abc
    >>> import six
    >>> @six.add_metaclass(abc.ABCMeta)
    ... class Base(object):
    ...     @abc.abstractmethod
    ...     def __whatever(self):
    ...             raise NotImplementedError
    ...
    >>> class SubClass(Base):
    ...     def __init__(self):
    ...             super(Base, self).__init__()
    ...             self.__whatever()
    ...     def __whatever(self):
    ...             print("whatever")
    ...
    >>> a = SubClass()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: Can't instantiate abstract class SubClass with abstract methods _Base__whatever
    

    When I change the implementation to the following, it works

    >>> class SubClass(Base):
    ...     def __init__(self):
    ...             super(Base, self).__init__()
    ...             self._Base__whatever()
    ...     def _Base__whatever(self):
    ...             print("whatever")
    ...
    >>> a = SubClass()
    whatever
    

    But this is very tedious , you may want to think about if you really want to define your functions with __ (double underscore) . You can read more about name mangling here .