[Python-3000] Implementations: A syntax for extending method dispatching beyond type/class inheritance
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.)
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).
Still there are common, if unrefined, conventions of using python I'd
like to see supported formally as well.
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
further refinement of this would be:
def get_name(arg: HasName):
but this refinement (in the syntax sketch), would force implementers to
declare the following implementation:
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
class Car(dict): # car... is a dict? hmm, a bad ring to it
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
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...
A implements Container:
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.)
More information about the Python-3000