[Python-3000] Implementations: A syntax for extending method dispatching beyond type/class inheritance
Dave Anderson
python3000 at davious.org
Thu Dec 7 06:52:35 CET 2006
on 12/3/2006 7:54 PM Bill Janssen wrote:
>> 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.
>
> I'm not sure just what this adds over the simple "change_class"
> function that I've posted twice already. Is there an implementation
> efficiency argument here?
There is more to the syntax sketch than class-vouching. Duck-typing and
method-subset implementation declaration/dispatching are included as
equally visible in this framework. I'll explain more below.
I've took a couple passes in the archives, and I haven't found the
change_class posts yet. I think you are referring to lying about the
__class__. Did I guess correctly? (Sorry, an archive link would help me.)
Inheritance-defined Relationships
=================================
I appreciate the cleanliness of the idea of relating all classes through
multiple inheritance of either concrete or abstract/type classes. A
subset of the syntax sketch supports this (basically as multi-methods
dispatching by implementations that happen to only use types).
Other-defined Relationships
===========================
Still there are common, if unrefined, conventions of using python I'd
like to see supported formally as well.
Has-Method Contracts
--------------------
The first thing I loved about python (coming from java), was this
realization that I was no longer need be caught up in the inheritance
game. If I wanted to use an unspoken convention that I could get a
special string from every object just by defining name() in each of
those objects, that's all I had to do. It didn't matter which class
tree it came from.
Looking at the syntax sketch, this can be formalized; but, its a low
level of formality that fits the context.
# (I used Generic.name in my original post, but that was a mistake.
# Sorry for my confusion, Phillip)
def get_name(arg: AnyClass.name): # AnyClass will magically have
return arg.name() # a reference to any method name
# somehow
further refinement of this would be:
class HasName:
def name(self):
...
def get_name(arg: HasName):
return arg.name()
but this refinement (in the syntax sketch), would force implementers to
declare the following implementation:
class X:
implements HasName
def name(self):
...
Has Class-specific Method Contracts
-----------------------------------
Similar to Has-Method Contracts are class-specific method contracts.
This is when you use a well-defined class as a way to indicate the
context of a method and separate it from homonyms.
def add_key_value_pair(arg: MutableContainer.add, key, value):
arg[key] = value
Implement (As a) vs Inherit (Is a)
----------------------------------
This is nuanced.
Basically, if I have some object Car and I want to be able to use it
like a dict, I don't necessarily consider it inheriting from dict (or
even UserDict). That is, I don't think a Car is a dict.
To me, even if Car happens to represent a dict by being able to be used
as a dict, the expression of this fact feels better expressed as merely
implementing dict.
compare:
class Car(dict): # car... is a dict? hmm, a bad ring to it
...
class Car:
implements dict # oh, Cars can be used like a dict, got it
...
In addition to that subjective differentiation, there is a technical
argument. Without something like an implements declaration, if I ever
want to express a relationship to another class, but with different
internals, I am forced to first define an abstract class and then
inherit from that. With an implements declaration, I can say implements
dict and be free of inheriting any of its internal implementation.
(I concede here that I could, in fact, inherit UserDict, override all
the methods, and just not call super in my init.)
Even with the nicely done ABCs, is there an easy way for a class to
declare that it can be used like a dict with its own implementation of
dict methods? With this syntax sketch, UserDict would remain the same
except:
class UserDict:
implements dict # dispatch can rely on this declaration
... # rather than method-checking
The Consequences of Going Outside of the Hierarchy
--------------------------------------------------
For all the above reasons, I want to see python support something more
flexible than type-based dispatching. We can look at the method-scoped
units of Implementations as a limited version of Guido's Abilities, and
we can look at the class-scoped implementations as types, or classes, or
also as abstract interfaces from concrete classes.
Unfortunately, I am now outside of the hierarchy tree; an implementation
tree would be a superset of a class's hierarchy tree. I suppose that
using dispatch this way is more complex compared to a strict class-based
set of relationships (because I am asking for checks not just on the
class-tree, but also on the implementations off that class-tree); but,
I'd rather fold current python usage into a future of type /
protocol-aware methods than force current pythonists into choosing
between class or no class, to type or not to type.
(Small Caveat:) Using Implementations as a Development Tool
------------------------------------------------------------
Btw, if we formally differentiate that I'm declaring an implementation
(versus inherit and override), I could programatically double-check my
implementation with tools...
class A:
implements Container
def len(self)
...
>>> interface_compliance(A)
A implements Container:
methods: len
missing: get, iterator
> What happens when you call an existing method from one of the
> (supertypes?) of an implementation? Do you have to re-implement it?
> Or do you have some way of coercing the value to that type?
In the syntax sketch, an Implementation is basically a list of
types/class, methods, and other Implementation lists.
You wouldn't call a method from an Implementation object.
(If I missed the gist of these questions. Please forgive me and clarify
them for me.)
>
> Bill
>
>
More information about the Python-3000
mailing list