Yet another attempt to deal with Interface concept in Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | #
# for interface-methods non redefined in classes
#
class AbstractError:
pass
#
# a kind of interface
#
class Copyable:
def copy(self):
return self.__copy__()
def __interface__(self):
assert self.__class__.__dict__.has_key('__copy__')
x = self.copy()
if hasattr(self,'__cmp__') or hasattr(self,'__eq__'):
assert x==self
assert x is not self
#
# Another kind of interface that require more elaborated
# testing.
# __interface__ method only check that the testing stuff
# has really be done.
#
class MyStackInterface:
def test_MyStackInterface(self, param1, param2):
self.append(param1)
self.append(param2)
assert self.pop() == param2
assert self.pop() == param1
self.__tested = 1
def __interface__(self):
assert self.__tested == 1
def append(self, data):
raise AbstractError
def pop(self):
raise AbstractError
#
# A sample of dummy class that define our two interfaces
#
class XX(Copyable, MyStackInterface):
def __init__(self):
self.data = []
def __copy__ (self):
o = XX()
o.data = self.data[:]
return o
def __eq__(self,other):
return self.data == other.data
def append(self,d):
self.data.append(d)
def pop(self):
return self.data.pop()
#
# Utilities functions for ensuring that classes well
# define interfaces.
#
def _test_interface(cl,obj):
if cl.__dict__.has_key('__interface__'):
cl.__interface__(obj)
for i in cl.__bases__:
_test_interface(i,obj)
def EnsureInterface(obj):
_test_interface(obj.__class__, obj)
#
# and now we do the tests
#
x=XX()
x.test_MyStackInterface(0,'foo')
EnsureInterface(x)
|
People sometime says that lack of formal interface specification make Python not suited for programming in the large.
Since interfaces in languages like Java or C++ only deal with syntax checking I don't think this construct would be usefull for a dynamic language like Python.
So I suggest to replace this static checking by tests. The interface manage a test suite, and any class that want to define an interface must pass this test suite. A mechanism ensure that, for every interfaces, the tests have been passed.