5

Let's assume that we have a Python class that makes use of the abc module to define an abstract attribute:

import abc

class A(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def test_attribute(self):
        raise NotImplementedError

Let's now consider to define B that subclasses from A by adding a new method (test_method()), and C that subclasses from B implementing the abstract method originally declared in A:

class B(A):

    def test_method(self):
        pass

class C(B):

    def test_attribute(self):
        # Implement abstract attribute
        pass

Assuming that I would like to keep B abstract (non-instantiable), shall I redefine the abstract property (test_attribute) and the metaclass assignment also in B? Or is it enough to inherit them from A (as in the above code)?

I know that Python allows me to not redefine the abstract methods and thus inherit them from the parent class. Is this correct from a theoretical software engineering perspective?

I'm asking so because if I'm not wrong other languages (such as Java) do not allow inheritance of abstract methods without reimplementing them as abstract...

TylerH
  • 20,799
  • 66
  • 75
  • 101
Andrea
  • 3,627
  • 4
  • 24
  • 36
  • "other languages (such as Java) do not allow inheritance of abstract methods without reimplementing them as abstract" - as long as the subclass is abstract (or an interface extending another interface), that's not true. You can inherit abstract methods in Java just fine. – user2357112 May 20 '14 at 20:10

1 Answers1

5

You've pretty much got all the code there, you can always test it and see if it works ... but as a spoiler, Your design is fine so long as C.test_attribute gets decorated with property.

If you try to make an instance of B, then you'll have problems since the whole abstract interface hasn't been created, but it is fine to create it as a base class for C (and presumably other classes later...)

e.g.:

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractproperty
  def foo(self):
    pass

class B(A):
  def bar(self):
    return "bar"

class C(B):
  @property
  def foo(self):
    return "foo"

print C().foo    # foo
print C().bar()  # bar
print B().foo    # TypeError
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • @Andrea: `__metaclass__` is no different from any other class attribute, and so is inherited from the parent class(es). (In the case of multiple inheritance, there are rules for determining which metaclass is actually used to create the child class if the parents have different metaclasses.) – chepner May 20 '14 at 20:10
  • @chepner -- Careful with that explanation. It works differently in python3.x where there is no `__metaclass__` attribute ... – mgilson May 20 '14 at 20:15
  • True. However, could one say that in Python 3, using the `metaclass` keyword sets the `__class__` attribute of the new class, which is then inherited by the subclass? – chepner May 20 '14 at 20:48