If some class extends abc class (Abstract Base Class) then I can't instantiate it unless I define all abstract methods. But often when implementing Decorator pattern, I want to define only a few abstract methods, and others - just delegate to decorated object. How to do this?
For example, I want to make the following code work:
from abc import ABCMeta, abstractmethod
class IElement(object):
__metaclass__ = ABCMeta
@abstractmethod
def click(self):
return
@abstractmethod
def hover(self):
return
# ... more IElement's abstractmethods...
class StandardElement(IElement):
def click(self):
return "click"
def hover(self):
return "hover"
# ... more implemented IElement's methods...
class MyElement(IElement):
def __init__(self, standard_element):
self._standard_element = standard_element
delegate(IElement, standard_element)
def click(self):
return "my click"
assert MyElement(StandardElement()).click() == 'my click'
assert MyElement(StandardElement()).hover() == 'click'
instead of
from abc import ABCMeta, abstractmethod
class IElement(object):
__metaclass__ = ABCMeta
@abstractmethod
def click(self):
return
@abstractmethod
def hover(self):
return
# ... more IElement's abstractmethods...
class StandardElement(IElement):
def click(self):
return "click"
def hover(self):
return "hover"
# ... more implemented IElement's methods...
class MyElement(IElement):
def __init__(self, standard_element):
self._standard_element = standard_element
def click(self):
return "my click"
def hover(self):
return self._standard_element.hover()
# ... more manually delegated IElement's methods to self._standard_element object, aggregated in initialiser...
assert MyElement(StandardElement()).click() == 'my click'
assert MyElement(StandardElement()).hover() == 'click'
For this I need to implement the delegate
method from example above. How to implement it? Some other approaches to provide automatic delegation for classes extending abc classes may also be considered.
P.S.
Please do not propose me Inheritance (class MyElement(StandardElement)
) as a solution here... The code provided above is just an example. In my real case MyElement is pretty different thing comparing to StandardElement. Still, I have to make MyElement compatible with StandardElement, because sometimes someone is supposed to use MyElement instead of StandardElement. I really need to implement "has a" relationship here, not "is a".
You get this error because the class
MyElement
is abstract (you haven't overridden the methodhover
). Abstract class is a class that has at least one abstract method. In order to resolve the error you should add this method in this way for example:If you want to delegate many methods using
__getattr__
it seems to be impossible viaabc.abstractmethod
, because__getattr__
dynamically searches for the necessary methods that are impossible to inspect without the direct running of__getattr__
.Therefore I would recommend you to specify all methods as abstract (via
@abstractmethod
) that surely will be overridden in each inherited class and implement the delegated method usingNotImplementedError
. An example: