Joose blog

Blog about Joose – advanced class system for JavaScript

Joose 3 internals – Part I. Meta-layers

with 3 comments

This post starts a series, describing the meta-model of the Joose3. It mostly purposed for people brave (or crazy) enough to hack on the internals, though casual users may find it also useful for deeper understanding of the underlaying processes in Joose.

Classes and meta-classes.

Ok, lets start with the definition what is the class. Its the abstract template or pattern, describing some behavior (for example: “Dog”). This template can be “instantiated” (usually arbitrary number of times) – that means the abstract definition receive a concrete implementation in some object (for example: “Pluto”). Such object will be called “an instance” of the class:

On the figure above and the following ones, the filled circles denotes classes, unfilled circles – instances.

Then, what is the meta-class? Its the class, whose instances, in turn, represents classes:

The meta-class defines the higher-level behavior of the class. For example it may define, that class can be only instantiated once. Or, that class may have special attributes with validation. Or, special methods with type-checking, etc.

Ok. You’ve probably already spotted the smell of recursion in the meta-class definition (its the class, whose instances are classes). Naturally, the chicken & egg problem arise – what is the meta-class of the meta-class itself? And what is the meta-class of that meta-meta-class?

Joose.Proto.Class – 1st meta-layer

The chicken & egg problem is being solved in Joose 3 by the 1st meta-layer, which is represented by the Joose.Proto.Class meta-class. Joose.Proto.Class is the class, which is the meta-class for itself! This makes its meta-instance perfectly circular – it refer to itself.

Classes with Joose.Proto.Class meta are very close to “raw” JavaScript and other simple class systems. Virtually everything from the class definition goes directly to the class prototype (except the “isa” builder). Inheritance is done with the “classical” prototype chain hack (see Joose.O.getMutableCopy in Joose.js)

If you really need “raw” JavaScript code (for animation library for example), you can host your class at this meta-level like this:

Class('Raw.Code', {
    meta    : Joose.Proto.Class,

    attr1   : 'init',
    attr2   : null,

    method  : function () { return 'result' }
})

var i = new Raw.Code()

i.method() == 'result' // true

At this meta-level there are no roles, traits, lazy attributes, method modifiers or any other magic, just JS. The other parts of the meta-model are written as classes from this meta-level. The next post will cover this topic in detail, in the meantime we’ll continue the overview of the other meta-layers.

Joose.Managed.Class – 2nd meta-layer

The next meta-layer is presented with Joose.Managed.Class. Joose.Managed.Class is a subclass of Joose.Proto.Class, and has it as a meta-class in the same time!


Important feature is that its safe to inherit from class, which has meta from the the previous layer:
This feature makes the bootstrapping possible.

Classes with Joose.Managed.Class as meta-class are already very capable. They may have method modifiers, roles or traits applied. At this level also appears the Joose.Managed.Role – a special meta-class, which, among other things, prevents class from instantiation.

However, we need one more bootstrapping step. The reason is that, by itself, Joose.Managed.Class has a Joose.Proto.Class as meta. Thus its behavior is very limited, you can’t apply role to Joose.Managed.Class for example. We definitely want our meta-model to have a more capable central meta-class. Another reason is the attributes. We need to be able to apply traits to the attributes. So the default meta-class for the attribute should be at least at “managed” level. But this level just been introduced – will be more elegant to delegate the change of the default attribute’s class to next layer.

Joose.Meta.Class – 3rd meta-layer

This is very simple meta-layer, required mostly for bootstraping purposes: Joose.Meta.Class.


There is also a corresponding Joose.Meta.Role meta-class.

Joose.Meta.Class is the central meta-class of the meta-model. If you need to modify the behavior of all classes, you can apply roles to it (comes in use for JooseX.Meta.Lazy for example). See also next section for explanations hows that possible.

Mutability

All classes in Joose, on all meta-levels are mutable. “Mutable” means that class/role definition can be changed at any time (add/remove attribute or method for example) and the change will be propagated to instances and other depended classes/roles.

Mutability is based on the fact, that during inheritance, prototypes of Joose classes forms the usual prototype chain. Thats why no special actions required when a class changes – the language itself will handle the propagation to sub-classes. A simple example:

var a = {

    method1 : function () { return 'a1' },
    method2 : function () { return 'a2' }
}

var b = Joose.O.getMutableCopy(a) // establish a prototype chain

b.method2 = function () { return 'b2' } // override a method

b.method1() == 'a1' // true
b.method2() == 'b2' // true

// mutation

delete a.method1
delete b.method2

b.method1 = function () { return 'b1' }
a.method3 = function () { return 'a3' } // add a new method to the base object

// eof mutation

b.method1() == 'b1' // true
b.method2() == 'a2' // true
b.method3() == 'a3' // true

Slightly more complex logic is required for roles mutations, but Joose never update the whole graph of depended classes, the most of work is delegated to JavaScript and  number of “manually” updated classes is as minimal as possible.

Conclusion

This post contains a high-level overview of the Joose meta-model. In the next post we’ll focus on the details of 2nd meta-level, which implements the traits specification.

Written by Nickolay Platonov

January 13th, 2011 at 9:02 am

Posted in Joose

Tagged with ,