Search code examples
pythonpolymorphismdynamic-dispatch

Dynamic Dispatch with a function passed in as a parameter


Example

class Parent:

  def foo(self):
    print('parent')


class DerivedA(Parent):

  def foo(self):
    print('derived A')


class DerivedB(Parent):

  def foo(self):
    print('derived B')

def bar(passed_in_func):
  temp = [DerivedA(), DerivedB()]
  for derived in temp:
    passed_in_func(derived)

bar(Parent.foo)

Output:

parent
parent

Output Desired:

derived A
derived B

Is there any way to call the derived class' function bar with the following constraints?

  1. There are multiple derived classes from Parent

  2. bar() will not necessarily know which of the derived classes is passed in

  3. The caller of bar() will not know which derived class function signature to pass in

EDIT

I know of one way to do this, but I see it as a little hacky:

def bar(passed_in_func):
  temp = [DerivedA(), DerivedB()]
  for derived in temp:
    getattr(derived, passed_in_func)()

bar('foo')

Solution

  • Here's a generic way of doing it that would work for immediate subclasses:

    class Parent:
        def foo(self):
            print('parent')
    
    
    class DerivedA(Parent):
        def foo(self):
            print('derived A')
    
    
    class DerivedB(Parent):
        def foo(self):
            print('derived B')
    
    
    def bar(passed_in_func):
        classname = passed_in_func.__qualname__.split('.')[0]
        parent = eval(classname)
        for derived in parent.__subclasses__():
            getattr(derived(), passed_in_func.__name__)()
    
    bar(Parent.foo)
    

    Output:

    derived A
    derived B