On Wed, Jul 13, 2005 at 07:27:52PM -0400, Stevan Little wrote: : The way I am viewing the notion of "current class" for submethods : currently is: : : From inside another method or submethod: : : - a submethod should only be called from the class which defines it.
This doesn't sound right to me. There is no distinction between inside or outside. A submethod is simply a method that says "These aren't the droids you're looking for" if you call it via either SMD or MMD dispatch and the first invocant isn't of the exact run-time type of the lexical class. In other words, it just has an implicit next METHOD if $?SELF != $?CLASS; at the front. So the dispatch continues until it finds either a submethod that does have an exact match or a method that isn't a submethod. : This means that since Object::bless() calls Object::BUILDALL() it is : all well and good, assuming you have not overridden bless() in your : class, and are calling it $class.bless(). No, Object::bless() (which perhaps delegates to Class.meta.bless so that different meta classes can have different .bless primitives) calls MyClass.CREATE to create the type, while will be an opaque type if that normal method dispatch runs up the tree to Object::CREATE. (But user classes are allowed to define their own CREATE method to create non-opaque objects.) After the storage is allocated, .meta.bless then calls $newobj.BUILDALL as an ordinary method call on the instance. Again this is overridable by each class, but typically goes back to Object::BUILDALL (which, as usual, probably delegates at least some of the work to the meta class). : (Object::BUILDALL of course then digs into the metaclass to call : BUILD() for all the superclasses in post-order. I am not sure how to do : that otherwise, submethod or not.) I believe there's pseudo-code for that in A12. The trick is that you can always force a call to a submethod of the "wrong" class by taking it as a sub reference and calling it like an ordinary subroutine. : However, if you define MyClass::bless, then you will need to define : MyClass::BUILDALL as well. We did not intend that people redefined .bless. It's really intended to be a primitive like .meta. The occasional redefinables are CREATE and BUILDALL, but it's really only intended that BUILD be defined typically. : Or is it possible just do $self.Object::BUILDALL()? So can I call a : submethod from a different class if I fully qualify it? No, that would just fail. You have to do the reference casting trick to call it as an ordinary subroutine. We made that hard on purpose. : From outside a method (in "user" space): : : - the invocant of the submethod must be a direct instance of the class : in which the submethod is defined. No inheritance involved. : : Maybe this is too strict, though? What do you think? There is no "user" space distinction. You still just call a method with the ordinary dispatcher, and it still just runs down the list of dispatcher class candidates till it either finds one that's a method or finds one that is a submethod and whose class matches the object's. Of course, that's highly unlikely to match a submethod on anything but the first probe, given the usual visitation order of the standard dispatcher and the fact that virtual method calls always start with the actual run-tiem type of the object, but MMD might have a different idea about order, and the same principle still applies. Plus other dispatchers are possible. The point of a submethod is that it doesn't make sense to call it on anything other than an actual object of this type (where initialization and finalization are examples of where we basically lie about the actual type because we want the various bit of the current object treated as if they were really an ancestral class even though they aren't really). Since that's the point of a submethod, the proper place to put the constraint is on the front of the submethod itself, and let it just fail to be dispatched to if it doesn't want to be dispatched to. In general, unless you are a funny dispatcher like .*foo, you shouldn't be thinking about "how you call them". : > There's some kind of "yes I mean : >you" notion in the dispatcher. It comes out in user-visible terms : >in .*foo calls but not ordinary .foo calls, : : I am not familiar with .*foo calls? Can you elaborate? This is all pretty much straight from A12. : > which call a submethod : >only when the object is actually that type, and otherwise look for an : >ancestral method of that name. : : Yes, to expand upon my above statements. The method resolution would : begin looking in the local submethod table, then move onto the local : method table, and then on up the superclass hierarchy. Is that correct? There is no separate submethod table. From the standpoint of ordinary .foo method resolution they're ordinary methods that happen to say "next METHOD" as a form of failure. The dispatcher doesn't even have to know they failed because they were a submethod and not because they didn't explicitly say "next METHOD". The dispatcher just says, "I guess they're not coming to the party," crosses that candidate off its list and goes on to the next one in the list. Larry