[Python-3000] Implementations: A syntax for extending method dispatching beyond type/class inheritance

Dave Anderson python3000 at davious.org
Mon Dec 4 01:16:00 CET 2006


Implementations are used to make Method Dispatching more flexible by 
allowing a class to claim that it acts like another class/type even 
though it is not derived from that class/type.

Method Dispatching

Class A:

# method 1
def f(arg):

# method 2
def f(arg: A):

method dispatching logic

if isinstance(arg, A):
     [use the method 2]

a = A()
f(a) # method 2 is used

*implements* keyword:
A simple Implementation claims it acts like a class/type

class B:
     implements A

method dispatching logic now becomes
if arg.does_implement(A):
     [use method 2]

b = B()
f(b) # method 2 is used

note, isinstance(o, T) -> True
will always guarantee o.does_implement(T) -> True

An Implementation can be Method-scoped

class Filelike:
     implements file.save

     def save(self):

def f(file_like_arg: file.save):
# will dispatch file and Filelike instances

An Implementation can be a combination of Classes and Class Methods

A_B_C_like = Implementation(A, B, C.f, C.g)

class D:
     implements A_B_C_like

def f(A_B_C_like_arg: A_B_C_like):
# will dispatch D instances

informal implementation lists are also allowed

class D1:
     implements A, B, C.f, C.g

def f(A_B_C_like_arg: A, B, C.f, C.g):
# will dispatch D and D1 instances

multiple implementation declarations are also allowed

class D2:
     implements A, B
     implements C.f, C.g

def f(A_B_C_like_arg: A, B, C.f, C.g):
# will dispatch D, D1, and D2 instances

*__adapt__* special method:
An Implementation can be tied to a special transformation method

class E:
     implements A

     def __adapt__(self: A):
         ... transformation statements ...
         return [transformed E instance]

When a E instance is dispatched as a A instance, __adapt__ will
used to generate a transformed instance

A default method can be overridden by a type specific method

class F
     implements A.f

     def f(self):

     def f(self: A):

When an F instance is dispatched as an A instance, a call to f
will use the second method

*employs* keyword:
Methods can be implemented by borrowing methods directly

class G:
     employs A, B.f, B.g

Class G will now use all of A's methods and method f and g of B

def f(c_var: A)
# will dispatch A and G instances

def g(c_var: B.f, B.g)
# will dispatch B and G instances

Ad Hoc and Runtime Implementation/Employment Declarations

class H:

def adaptation_method(self):
     return [transformed self]

H.implements(A, B, C.f)
H.adapt(D, adaptation_method)


h = H()
h.employs(F) # object h (not class H) implements F with F's methods

Implementing non-class-specific methods using special Generic type

class I:
     def f(self):

     def g(self):

I.does_implement(Generic.i, Generic.g) -> True

Implements supports many related conventions

Supported with the implements keyword

Supported with method-scope implementation units and,
if desired or needed, Generic methods

Abstract Interfaces
Supported by implementing classes with empty method definitions

Homonym Method Resolution
Resolved by overloading self in method definitions

Supported with implements and the __adapt__ special method

(Informal) Mix-ins
Supported using the employs keyword

Interesting Examples for Clarification

In order to be treated as a type/class, a type/class (versus 
method-unit) implements  or employs declaration must be used

class A:
     def f(self):

     def g(self):

class B:
     implements A.f, A.g

B.does_implement(A) => False

That is to say, if you want the fine-grain level
that duck-typing provides, you must be explicit

a_methods_implementation = Implementation(A.f, A.g)

B.does_implement(a_methods_implementation) => True

there could be an Object-level property that collects an implementation 
list based on all the classes methods...

B.does_implement(A.duck_implementation) => True

there could be an Object-level property that collects an implementation 
list in terms of Generic methods

B.does_implement(A.generic_implementation) => True

An Implementation declaration does not affect isinstance

class I:
     implements A

i = I()

isinstance(i, A) -> False
i.does_implement(A) -> True

Implementation declarations are inherited like classes,
  but through a separate inheritance chain

class J:
     implements A

class K(J):

K.does_implement(A) -> True

Undeclared method assignments aren't added to
  a class's implementation list automatically

class L:
     f = B.f

L.does_implement(B.f) -> False

class M:
     employs B.f

M.does_implement(B.f) -> True

More information about the Python-3000 mailing list