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