Timothy Baldridge
Timothy Baldridge

Reputation: 10683

Any way to get "interfaces" with Cython?

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

Answers (1)

DavidW
DavidW

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:

  1. you either register your class as belonging to an interface ("abstract base class") like I've done for InterfaceA, or
  2. you give your interface a __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

Related Questions