On Oct 12, 2005, at 09:41, Stevan Little wrote:

If you use the BUILD submethod, then you never need to worry about a that, everything is initialized for you by BUILDALL. Now, if you want to have a constructor which accepts positional arguments rather than named pairs (as the default does), then you have a valid need to override &new. Whether you should force this upon all your subclasses is a matter of opinion I think.

For varying definitions of initialized. I never much cared for the bare "poke stuff straight into my instance variables" constructor along the lines of:

    sub new {
        my($class, %ARGS);
        return bless \%ARGS, $class;
    }

That more or less robs the constructor of the "behavior" part of "class = state + behavior." I need an opportunity to establish my invariants.

Of course, when there is no such behavior, it saves a lot of repetitive typing in the class. C# 3 is finally growing a syntax that resolves this by having the language do the repetitive typing at the call site...

    X x = new X{ Y = 1, Z = 2 };

means

    X x = new X();
    x.Y = 1;
    x.Z = 2;

And X doesn't need anything but the default constructor.


Now, this is not to say that it cannot be made to do so. A slight change to the above diagram allows for inheritence of "class methods" very easily.

  Class
    ^
    :
  eFoo<.......eBar
    ^          ^
    |          |
   Foo<.......Bar

Now, method dispatch for Bar will go first to it's class (eBar), then to any superclasses (eFoo), and any of their superclasses (Class), and so on, and so forth. A better diagram of this can be found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ docs/Method_Dispatch_w_EigenClasses.jpg).

This is more or less how class methods have to work. I would go a bit further, though. Too implement this:

    Foo : Object
    Foo : Bar

The runtime should use an inheritance tree as such:

    Object
    Class : Object
    Foo : Object
    Bar : Foo

    _Object : Class
    _Class : _Object
    _Foo : _Class
    _Bar : _Foo

Note that every declared class, including Object and Class themselves, have an anonymous Class subclass that precisely parallels the declared inheritance chain. (Chicken and egg problem? Probably. Object and Class are Special.)


With this implementation, there are three places to put state: In MyObject (instance variable), in _MyObject (class instance variable), or outside of any instance (class variable). The class instance variable is the least useful of the three.


Note: I don't see much value in invoking class methods through instances, since a Foo IS_NOT_A Class. If one wants to save the user typing ".class" when invoking class methods through an instance, I would tend toward resolving it as such:

class Foo {
    class_method int Bar(int i) { return i * i; }
}

-- BECOMES --

# Common interface for Foo's class methods.
interface _IFoo {
    method int Bar(int i);
}

# The anonymous Class.
class _Foo extends Class implements _IFoo {
    int Bar(int i) { return i * i; }
}

# The visible class.
class Foo implements _IFoo {
    # Forwards the call to the Class.
    void Bar(...) { return this.Class.Bar(...); }
}

I'll leave the probably obvious role-based interpretation of this to those versed in such. :)


And I'm going to shut my yap, now, having butted into the middle of a discussion of a hopelessly complex runtime that I haven't been following for a 18 months. :)

—

Gordon Henriksen
[EMAIL PROTECTED]


Reply via email to