Reputation: 10683
My application needs to have several Cython cdef
classes that inherit from a single base class, but yet still implement many interfaces. These interfaces would be used to do isinstance()
checks on the classes to make sure they conform to certain interfaces.
I know Cython doesn't support multiple inheritance, but is there any way at all to implement interface-like behavior. It seems like a rather glaring limitation in Cython and I'm sure I'm not the only person to encounter this problem.
Upvotes: 3
Views: 1287
Reputation: 30916
You do it exactly as you would in pure Python when faced with a base class that you can't change but that you want to associate with an interface: you use the abstract base classes module
There's two options to chose from:
register
your class as belonging to an interface ("abstract base class") like I've done for InterfaceA
, or __subclasshook__
that allows it to claim any class with the right methods like I've done for InterfaceB
.Example:
import abc
# define the interfaces as normal (non-Cython) Python classes
class InterfaceA(metaclass=abc.ABCMeta):
# Python3 syntax. metaclasses are slightly different in python2
pass
class InterfaceB(metaclass=abc.ABCMeta):
@abc.abstractmethod
def useful_function(self):
raise NotImplementedError()
@classmethod
def __subclasshook__(cls,other_cls):
if cls is InterfaceB:
if any("useful_function" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
# our Cython class
cdef class C:
def useful_function(self):
return 1
c = C()
print(isinstance(c,InterfaceA)) # prints False
InterfaceA.register(C)
print(isinstance(c,InterfaceA)) # prints True
print(isinstance(c,InterfaceB)) # prints True
Upvotes: 5