Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract class + mixin + multiple inheritance in python

So, I think the code probably explains what I'm trying to do better than I can in words, so here goes:

import abc  class foo(object):     __metaclass__ = abc.ABCMeta     @abc.abstractmethod     def bar(self):         pass   class bar_for_foo_mixin(object):     def bar(self):         print "This should satisfy the abstract method requirement"   class myfoo(foo, bar_for_foo_mixin):     def __init__(self):         print "myfoo __init__ called"         self.bar()  obj = myfoo() 

The result:

TypeError: Can't instantiate abstract class myfoo with abstract methods bar 

I'm trying to get the mixin class to satisfy the requirements of the abstract/interface class. What am I missing?

like image 600
mluebke Avatar asked May 05 '09 17:05

mluebke


People also ask

Can abstract class support multiple inheritance?

Inheritance is another feature of object-oriented programming where a particular class can derive from a base class. Multiple inheritance allows the extension of more than one base class in a derived class. Abstract classes do not support multiple inheritance.

Is Mixins multiple inheritance?

A mixin is typically used with multiple inheritance. So, in that sense, there's "no difference". The detail is that a mixin is rarely useful as a standalone object.

Can mixin be abstract?

It's common to implement mixins using abstract classes in Java, as the abstract keyword notes that the class is designed for reuse and isn't mean to be used by itself (it also obviously prevents you from using it by itself).

Does Python support multiple inheritance in Python?

Yes, Python supports multiple inheritance. Like C++, a class can be derived from more than one base classes in Python. This is called Multiple Inheritance.


2 Answers

Shouldn't the inheritance be the other way round? In the MRO foo currently comes before bar_for_foo_mixin, and then rightfully complains. With class myfoo(bar_for_foo_mixin, foo) it should work.

And I am not sure if your class design is the right way to do it. Since you use a mixin for implementing bar it might be better not to derive from foo and just register it with the 'foo' class (i.e. foo.register(myfoo)). But this is just my gut feeling.

For completeness, here is the documentation for ABCs.

like image 188
nikow Avatar answered Oct 03 '22 03:10

nikow


i think (tested in similar case) that reversing the baseclasses works:

class myfoo(bar_for_foo_mixin, foo):     def __init__(self):         print "myfoo __init__ called"         self.bar() 

so in the mro() it would find a concrete version of bar() before it finds the abstract one. No idea if this is actually what happens in the background though.

Cheers, Lars

PS: the code that worked in python 2.7 (python 3 has a different way to set metaclasses) was:

class A(object):     __metaclass__ = abc.ABCMeta      @abc.abstractmethod     def do(self):         pass  class B(object):     def do(self):         print "do"  class C(B, A):     pass  c = C() 
like image 29
Lars Avatar answered Oct 03 '22 05:10

Lars