Let there be an abstract class Animal
which is extended and implemented by class Dog
and class Cat
.
class Animal:
def speak(self):
raise NotImplementedError
... # 50 other methods with implementation and another 40 without implementation (abstract, headers only)
class Dog(Animal):
def speak(self):
return "ruff"
... # 40 more implemented methods
class Cat(Animal):
def speak(self):
return "purr"
... # 40 more implemented methods
There is also a bunch of functionality that can turn Animals
into RoboAnimals
, which causes every Animal
type to say "beep boop" before anything whenever they speak
.
How should one implement both a class RoboDog
and a class RoboCat
while avoiding duplicating code? Neither Dog
, Cat
, or Animal
can be manipulated.
I've tried using another class
-- RoboAnimal
-- that extends Animal
in order to cover for 50 basic Animal
methods, but Animal
has 40 other abstract methods that need appropriate implementation (Dog
/Cat
). If I use composition, and simply wrap a Dog
or Cat
instance, I'd still have to make sure that all Animal
methods called on this object behave accordingly to whether the flying animal is actually a Dog
or a Cat
.
Just to be clear, a RoboDog
returns "beep boop ruff"
on .speak()
calls and otherwise behaves like a Dog
, and likewise with Cat
("beep boop purr"
).
Can you do that in Python 3.10?
EDIT: My attempts at solving the problem:
#1
class RoboDog(Dog):
def speak(self):
return "beep boop " + super().speak()
class RoboCat(Cat):
def speak(self):
return "beep boop " + super().speak()
# damn, I've just duplicated the code...
# what if adding robotic functionality
# to animals took hundreds of lines of
# code, now that would be a hassle to maintain
#2
class RoboAnimal(Animal):
def speak(self):
return "beep boop " + super().speak()
# oh snap, super().speak() raises an error :(
#3
class RoboAnimal(Animal):
def __init__(self, animal_cls, ...):
super().__init__(...)
self.wrapped_animal = animal_cls(...)
def speak(self):
return "beep boop " + self.wrapped_animal.speak()
# now this is epic, but none of the 40 abstract methods work now