« Return to Thread: mixins etc.

Re: mixins etc.

by Andres Almiray :: Rate this Message:

Reply to Author | View in Thread

Great! though I would like to see what Luke and Alexandru bring to the table,
as they were also looking into mixins for Groovy (Luke made Injecto after all)

-- Andres

Alex Tkachman wrote:
After discussion in the list I am ready to commit first draft of
mixins implementation. This work is side result of some internal
refactorings in meta class implementation and can easily be switched
off. The reason I want it to be in the trunk is to give people chance
to play with it and find what is good and what is bad in the approach
and implementation.

So what is mixin?

Mixin is usual category-like class, which provides methods to extend
some (or several) existing classes.

class ArrayListExt {
   static def newArrayListMethod (ArrayList self) {
        "result of newArrayListMethod "
   }
}

simple use of it

ArrayList.mixin ArrayListExt

and now you can use

assertEquals "result of newArrayListMethod ", [].newArrayListMethod ()

Of course, you can mix class with several other classes at the same time

ArrayList.mixin ArrayListExt, ListExt, CollectionExt

For groovy obejcts where is even nicer compile time way to achieve
almost the same

@Mixin(MyClassExt)
class MyClass {
     def result () {
         longRunningJavaMethod ()
     }
}

and write for example in Java

public MyClassExt {
         public static Set<Collection> longRunningJavaMethod (MyClass
self) { /// }
}

In fact @Mixin in implemented with help of Class.mixin method. Thanks
for wonderful AST transformations call to this method added in to
static initialization of the class.

You can wonder here why don't create methods for mixins in compile
time. It is perfectly doable. Just don't implemented. We need to think
does it make sense or not.

Another nice feature for groovy objects is ability to do per instance mixins

def  groovyObject = new MyClass ()
groovyObject.mixin MyClassExt
groovyObject.longRunningJavaMethod () // will work only for this
particualr instance

How does it work?

To understand how all that works we need to remember how our MOP
selects methods. We have four layers. Each of these overrides previous
one.

1) Methods of the class and super classes (including all their
modifications except categories)
2) DGM methods
3)
4) EMC methods
5) methods of categories in use

As you noticed I said "four layers" but mentioned five and left 3)
blank. The reason is it is exactly the place which mixin methods take.
They go to the same method index as original methods and DGM. Any EMC
methods and categories applied on top of that.

So what happen when you add mixins in to the class is recreation of
meta class. So far we able to recreate meta classes for MetaClassImpl
and ExpandoMetaClass, otherwise runtime exception is thrown.

It is important to note that when we apply mixin to class dynamically
(not on compilation time or in static initializer) it might happen
that meta classes already created for some derived classes and will
not be effected. EMC does special and complicated tricks to handle
missing methods by checking super classes. I don't do the same for
mixins right now. I think in the future we can easily get rid of that
and combines mixin and EMC methods in the same layer and just
automatically recreate meta classes. Fortunately now it is relatively
cheap operation compare to the very expensive past.

Please play with trunk and comment. If we finally decide to switch it
off it will be very easy.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

 « Return to Thread: mixins etc.