[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