My attempt at answering this question draws on this question: Cast base class to derived class python (or more pythonic way of extending classes)
I'm writing a mixin class that will add some functionality to an object returned by another module. The code in the other module looks like this:
class Foo(Mixin):
def __new__(cls, *args, **kwargs):
#...handle a bunch of cases
if case1:
return FooTypeA
elif case2:
return FooTypeB
#... etc
class FooTypeA(Mixin):
#...
class FooTypeB(Mixin):
#...
I've written MyMixin, which adds a little bit of functionality to the objects returned by Foo. My attempt at solving the problem is this:
from other_module import Foo, FooTypeA, FooTypeB, ...
class MyFoo(Foo):
def __new__(cls, *args, **kwargs):
#...handle most of the same cases
if case1:
ret = FooTypeA(*args, **kwargs)
ret.__class__ = MyFooTypeA
if case2:
ret = FooTypeB(*args, **kwargs)
ret.__class__ = MyFooTypeB
#... etc
class MyFooTypeA(FooTypeA, MyMixin):
pass
class MyFooTypeB(FooTypeB, MyMixin):
pass
This looks really, really ugly. Is there really no better solution?
If not, why?
EDIT: I thought it would be easier without going in to speicifics, but the code I'm actually working on is here. The author of this module has written "WebDriverMixin," which mostly provides some nicer syntax for accessing elements on the page that an instance of the selenium webdriver is on. I have "SiteSpecificMixin," which provides some nicer syntax for accessing elements of the particular site that I'm testing.
webdriverplus.WebDriver
returns instances of webdriverplus.Firefox
, webdriverplus.Chrome
, webdriverplus.Ie
, etc. webdriverplus.Firefox
inherits from webdriverplus.WebDriverMixin
and selenium.webdriver.firefox.webdriver.Firefox
, webdriverplus.Chrome
inherits from webdriverplus.WebDriverMixin
and selenium.webdriver.firefox.webdriver.Chrome
, etc.
I want to add functionality to the objects that webdriverplus.Webdriver
returns, which seems like it requires making a class, mysite.SiteSpecificDriver
, copy+pasting the body of webdriverplus.WebDriver.__new__
into mysite.SiteSpecificDriver.__new__
, and then writing mysite.Firefox
(which needs to inherit from webdriverplus.Firefox
and mysite.SiteSpecificMixin
), mysite.Chrome
(which needs to inherit from webdriverplus.Chrome
and mysite.SiteSpecificMixin
), etc, and re-handling all of the browsers inside my own module that the original author handles in his.
I'm handling it now with code like in my example above, and it works. I'm new to OOP, but my understanding of OO techniques is that they're supposed to let you avoid code that has long if-elif-...-else clauses that depend on what type of object you're working with, so I think that I must be doing something wrong.