15

MyBase is forcing implementation of method f() in all children. This can be achieved either by using abc.ABCMeta to make f() an abstractmethod:

import abc


class MyBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def f(self, x):
        pass

class Child1(MyBase):
    def f(self, x):
        print(x)

class Child2(MyBase):
    pass

Child1().f(4)   # prints 4
Child2().f(4)   # TypeError: Can't instantiate abstract class Child2 with abstract methods f
MyBase()        # TypeError: Can't instantiate abstract class MyBase with abstract methods f

..or alternatively, by NotImplementedError:

class MyBase():

    def f(self, x):
        raise NotImplementedError('Abstract method not implemented.')

class Child1(MyBase):
    def f(self, x):
        print(x)

class Child2(MyBase):
    pass

Child1().f(4)   # prints 4
Child2().f(4)   # raises implementation error
MyBase()        # does NOT raise error

Using an abstract class instead of returning NotImplementedError disallows for example accidental instantiation of MyBase().

Are there any other benefits (or drawbacks) from using an abstract class over NotImplementedError?

2 Answers 2

14

You should use an abstract class because it is the appropriate choice for your model, not because of some desired side effect. So instead of thinking benefits, think meaning.

An abstract class classifies classes and allows you to group common data and behavior for that group of classes. If that fits your problem domain (you recognize multiple classes with common properties), use an abstract class. If it does not and you just want to hint an implementor to complete an implementation, create a template or something and throw your exceptions.

Not being able to create an instance of an abstract class is not a "drawback" of the thing, it is inherent to its purpose.

3
  • 1
    "if [...] you recognize multiple classes with common properties, use an abstract class" - Can't that be accomplished by NotImplementedError along with appropriate naming of the base class (e.g. ButtonBehavior as a base for all Button-like classes)?
    – user
    Commented Jul 31, 2016 at 9:27
  • 1
    Yes, you could create a class for common stuff and then have all button like classes contain an instance of the CommonButtonStuff class. Although that would in this case defeat the purpose of OO. Sometimes however inheritance is not helpful, when different types still need common behavior. Then your suggestion or interfaces would be more appropriate. Commented Jul 31, 2016 at 12:04
  • looking at this I see abstractmethod as the generally better solution, but if the parent isn't meant to be called by the child is there any reason to use pass instead of just raising NotImplementedError() within the abstract method? This does a few things: makes sure a call to super is deterred; works as more readable documentation for those less familiar with abstractmethod, and is a backup should someone delete/copy and miss the decorator Commented Oct 21, 2020 at 6:58
4

"Abstract class" is a general programming concept. An abstract class as a programming concept is a class that should never be instantiated at all but should only be used as a base class of another class.

In some languages you can explicitly specifiy that a class should be abstract. For example, in C++ any class with a virtual method marked as having no implementation. In some languages, there is no such thing.

If your language allows it, write abstract classes in a way that explicitely marks them as abstract. If not, either use some other means that let you detect instantiation of an abstract class, or just ignore the problem because using an instance of an abstract class will not likely produce any usable result.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.