[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


Summary
=======

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.employs(E)

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
============================================

Class/type-vouching
-------------------
Supported with the implements keyword


Duck-typing
-----------
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


Adaptation
----------
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