Python: Should I use delegation or inheritance here?
delegation, inheritance, oop, python, python-3.x
Solution
B) An elegant solution would be to use delegation plus some special method that forwards all attribute and method accesses which Anaconda does not respond to to its instance of Python.
This is simple in Python, just define `__getattr__`:
class Anaconda:
def __init__(self, python):
self.python = python
def wriggle(self):
self.python.snake()
def devourCrocodile(self, croc):
...
def __getattr__(self, name):
return getattr(self.python, name)
See the Python docs on `__getattr__`
Problem
I am pondering if I should use inheritance or delegation to implement a kind of wrapper class. My problem is like this: Say I have a class named `Python`. ``` class Python: def __init__(self): ... def snake(self): """ Make python snake through the forest""" ... def sleep(self): """ Let python sleep """ ... ``` ... and much more behavior. Now I have existing code which expects an `Anaconda`, which is almost like a `Python`, but slightly different: Some members have slightly different names and parameters, other members add new functionality. I really want to reuse the code in `Python`. Therefore I could do this with inheritance: ``` class Anaconda(Python): def __init__(self): Python.__init__(self) def wriggle(self): """Different name, same thing""" Python.snake(self) def devourCrocodile(self, croc): """ Python can't do this""" ... ``` Of course I can also call `Anaconda().sleep()`. But here is the problem: There is a `PythonFactory` which I need to use. ``` class PythonFactory: def makeSpecialPython(self): """ Do a lot of complicated work to produce a special python""" … return python ``` I want it to make a `Python` and then I should be able to convert it to an `Anaconda`: ``` myAnaconda = Anaconda(PythonFactory().makeSpecialPython()) ``` In this case, delegation would be the way to go. (I don't know whether this can be done using inheritance): ``` class Anaconda: def __init__(self, python): self.python = python def wriggle(self): self.python.wriggle() def devourCrocodile(self, croc): ... ``` But with delegation, I cannot call `Anaconda().sleep()`. So, if you're still with me, my questions are: A) In a case similar to this, where I need to - add some functionality - rename some functionality - use "base class" functionality otherwise - convert "base class" object to "subclass" object should I use inheritance or delegation? (Or something else?) B) An elegant solution would be to use delegation plus some special method that forwards all attribute and method accesses which `Anaconda` does not respond to to its instance of `Python`.