Hey All,
So, given the abundance of positive responses ;) for my "class
methods don't inherit" proposal, I have decided to withdraw that
proposal (see my last response on the thread). Of course, this means
we now have to work out the details of exactly *how* they get
inherited in all situations. The trickiest one being in the presence
of custom metaclasses. So, onto the questions.
(NOTE: if you get bored about half-way through this mail (and you
probably will), there is a conculsion/wrap-up at the very bottom that
you can probably safely skip ahead too)
Should custom metaclasses are "inherited" along "normal" subclass lines?
This would mean that if Foo uses CustomMeta as it's metaclass, any
subclass of Foo will do the same. This is something Larry mentioned,
and something I had been thinking about a lot myself and discussed
recently with Rob Kinyon. I drew a diagram in my response to Larry
that looked like this:
Class
^
:
CustomMeta
^
:
eFoo<...eBar
^ ^
| |
Foo<...Bar
This shows the structure which would be created. The result is that
method dispatch would go like this:
Bar.foo
eBar.get_method(foo)
eFoo.get_method(foo)
CustomMeta.get_method(foo)
Class.get_method(foo)
! No Method Found Error !
I think this makes sense in many ways since CustomMeta can
theoretically add capabilities to the Foo class, which one would want
inherited by subclasses of Foo. (NOTE: if CustomMeta adds instance
methods to Foo, they will get inherited, mostly I am talking about
class functionality here)
However, I can also see where it would make sense for this *not* to
behave this way. But if we the opposite approach, the eigenclass/
metaclass hierarchy begins to get more complex.
To start with, we would need to create another anon-class (called
xFoo here) which uses multiple inheritence to inherit from eFoo and
CustomMeta, then eBar would inherit from eFoo (and through eFoo, to
Class), this would keep CustomMeta out of Bar's method dispatch path.
Class
^^...
: :
CustomMeta :
^ :
: :
xFoo...>eFoo<...eBar
^ ^
| |
FooeFoo xBar>eBar
^ ^ ^:
| :.|:
| |
Foo<..Bar
The method dispatch path for this is pretty much the same as above,
with the addition of CustomMeta2. This example now actually brings up
another issue.
What should the superclass ordering be within the x* classes?
If eBar comes first, followed by CustomMeta2, then we get the
following method dispatch path:
Bar.foo
xBar.has_method(foo) # xBar should never have any of it's own method
eBar.has_method(foo)
eFoo.has_method(foo)
CustomMeta2.has_method(foo) # this would fall here under C3
Class.has_method(foo)
! Method Not Found Error !
But if CustomMeta2 comes first, followed by eBar, then we get the
following method dispatch path:
Bar.foo
xBar.has_method(foo)
CustomMeta2.has_method(foo)
eBar.has_method(foo)
eFoo.has_method(foo)
Class.has_method(foo)
! Method Not Found Error !
The question really is, which has precedence, the custom metaclass,
or the local class methods (including class methods inherited along
"normal" class lines)?
Now, all these method dispatch paths are using the C3 MRO. And
personally I find neither of these approaches to be the best. One
alternate (but kind of whacky) approach would be to not use C3 here,
but instead use breath-first traversal.
Now, this may seem really odd at first, but given the highly regular
structure of these class groupings, it might make the most sense.
Here is what that method dispatch path might look like:
Bar.foo
xBar.has_method(foo)
eBar.has_method(foo)
CustomMeta2.has_method(foo)
eFoo.has_method(foo)
Class.has_method(foo)
! Method Not Found Error !
Notice how the eBar (which hold's Bar's class methods) is first,
followed by the CustomMeta2 class, the followed by eFoo, then onto
Class.
This specialized dispatching beha