Reputation: 145
Note I do not think that abc inherently solves what I'm looking for. Restating in another, maybe better way, I'm looking of a way to partially implement a Parent.method but require that there is a Subclass.method also, which uses and adds to the partial Parent.method implementation.
I would like to partially define an abstract class method, but still require that the method be also implemented in a subclass. For example:
class AbstractClass(object):
def amethod():
# some code that should always be executed here
vars = dosomething()
# But, since we're the "abstract" class
# force implementation through subclassing
if <somehow determine whether this has not been subclassed>:
raise NotImplementedError
class ActualClass(AbstractClass):
def amethod():
# Actual class code
code_here()
# And execute the super class code.
super(ActualClass, self).amethod()
Upvotes: 3
Views: 5182
Reputation: 1677
I use to call this "fill-in-the-blank pattern" (NB: this is not a design pattern). You define a concrete method in the abstract class which calls abstract methods and works as a template with "blanks" (the abstract methods). The sub-classes "fill the blanks" implementing the abstract methods. In your simple case:
class AbstractClass(object):
def amethod(self):
self._amethod()
print('Common operations')
@abc.abstractmethod
def _amethod(self, vars):
pass
class ConcreteClass(AbstractClass):
def _amethod(self):
print('Concrete class code')
Usually you can give a better name to the abstract method.
Upvotes: 0
Reputation: 1156
Note I do not think that abc inherently solves what I'm looking for.
Actually abc
is exactly what you're looking for. Defining an implementation in
the base class but decorating it as abstract requires deriving classes to redefine it.
Of course this has the side effect of preventing you from instantiating the base class,
which I assume is OK in your use case.
import abc
# inheritance from abc.ABC is important, as otherwise the decorators don't do anything
class AbstractClass(abc.ABC):
@abc.abstractmethod
def amethod(self):
# some code that should always be executed here
print("Base implementation")
class ActualClass(AbstractClass):
# will return TypeError: Can't instantiate abstract class ActualClass with abstract methods amethod if not redefined
def amethod(self):
# Actual class code
print("Actual implementation")
# And execute the super class code. (only one super class so less confusing)
super().amethod()
a = ActualClass()
a.amethod()
Upvotes: 4
Reputation: 7548
Also this is interesting
def abstractmethod(method):
def default_abstract_method(*args, **kwargs):
raise NotImplementedError('call to abstract method ' + repr(method))
default_abstract_method.__name__ = method.__name__
return default_abstract_method
http://code.activestate.com/recipes/577666-abstract-method-decorator/
Though I haven't used it.
Upvotes: 1
Reputation: 7548
Test like this?
class AbstractClass(object):
def amethod(self):
# some code that should always be executed here
print(" AbstractClass.amethod()")
# But, since we're the "abstract" class
# force implementation through subclassing
if self.__class__ == AbstractClass:
raise NotImplementedError
class ActualClass(AbstractClass):
def amethod(self):
# Actual class code
print(" ActualClass.amethod()")
# And execute the super class code.
super(ActualClass, self).amethod()
#a = AbstractClass()
#a.amethod()
b = ActualClass()
b.amethod()
Upvotes: 1
Reputation: 4998
You could force it by raising an exception in the parent:
class base(object):
def a_method(self):
raise NotImplementedError("Implement this!")
class second(base):
pass
I would get an exception if I call second().a_method()
. There's no such thing as abstract in Python, but this is likely your best way of doing it. Otherwise,
import abc
class base(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def something_to_implement(this):
"""A docstring"""
return
This will make the method "abstract" by attempting to raise a TypeError
if initialized.
Upvotes: 0