lundi 18 avril 2022

Intercept specific function invocations using parent/child classes?

I am writing a framework that allows us to intercept certain function invocations so that we can manage them(enforce timeouts and retries, persist return values etc.). Right now I'm thinking of introducing an abstract class with a method that invokes an abstract method and forcing users/clients to inherit the abstract class and do their function invocations inside the abstract method.

Specifically, I am writing an abstract class Fruit that expects clients to:

  1. Extend Fruit and override the eat_fruit method
  2. Invoke the eat method when actually wanting to use the overriden eat_fruit method

The reason I'm thinking of doing this is that we want to record the number of eat_fruit invocations

class Fruit:
    def eat(self, *args, **kwargs):
        self.eat_fruit(*args, **kwargs)
        
    def eat_fruit(self, *args, **kwargs):
        pass

class Apple(Fruit):
    def eat_fruit(self, *args, **kwargs):
        print("Eat Apple")
        
apple = Apple()
apple.eat()

However, we're running into a problem with extensibility. Let's say the client needs to add input parameter color to Apple's eat_fruit method, they can add it like this:

class Fruit:
    def eat(self, *args, **kwargs):
        self.eat_fruit(*args, **kwargs)
        
    def eat_fruit(self, *args, **kwargs):
        pass

class Apple(Fruit):
    def eat_fruit(self, color, *args, **kwargs):
        print("Eat "+ color + " Apple")
        
apple = Apple()
apple.eat("Red")

This is workable but relies on them knowing that Fruit's eat method passes *args and **kwargs directly to the eat_fruit method, which seems to be an implementation detail in the eat method that may be subject to change.

I'm wondering if there are better ways to accomplish the same thing. In particular,

  1. Is it possible for them to invoke eat_fruit directly(rather than invoking the parent class's eat method and assume that the arguments will be forwarded to eat_fruit)? I can't think of a way for them to do that while still letting us keep track of eat_fruit invocations
  2. Is there a better way(rather than using parent-child classes) to intercept function invocations? The final goal of this framework is to intercept specific function invocations made by clients so that we can manage them(enforce timeouts and retries, persist return values etc.).

Thanks! Jessica

Aucun commentaire:

Enregistrer un commentaire