Jam is an extension of the Java language supporting mixins, that is parametric heir classes.
|
|||
A mixin declaration in Jam is similar to a Java heir class declaration, apart that it does not extend a fixed parent class, but simply specifies the set of fields and methods a generic parent should provide. In this way, the same mixin can be instantiated on many parent classes, producing different heirs, thus avoiding code duplication and largely improving modularity and reuse. Moreover, as happens for classes and interfaces, mixin names are reference types, and all the classes obtained instantiating the same mixin are considered subtypes of the corresponding type, hence can be handled in a uniform way through the common interface. This possibility allows a programming style where different ingredients are "mixed" together in defining a class; this paradigm is partly similar to that based on multiple inheritance, but avoids its complication. | |||
The language has been designed with the main objective in mind to obtain, rather than a new theoretical language, a working and smooth extension of Java. That means, on the design side, that we have faced the challenging problem of integrating the Java overall principles and complex type system with this new notion; on the implementation side, that we have developed a Jam to Java translator which makes Jam programs executable on every Java Virtual Machine. |
Consider the following mixin declaration:
mixin Undo {
inherited public String getText() ;
inherited public void setText(String s) ;
public String lastText = "" ;
public void setText(String s) {
lastText = getText() ;
super.setText(s) ;
}
public void undo() {
setText(lastText) ;
}
}
This mixin, as the name suggests, provides an "undo" mechanism that permits
to restore the text before the last modification. As shown in the example, a mixin
declaration is logically split in two parts: the declarations of the components which are
expected to be provided by the parent class, prefixed by the inherited
modifier, and the declarations of the components defined in the mixin. Note that defined
components can override/hide inherited components, as it happens for usual heir classes.
The mixin Undo
can be instantiated on classes that define two non-abstract
methods getText
and setText
, with types as specified in the inherited
declaration.
The next code snippet shows an example of instantiation; we have used as parent the class Example
.
class Example { private String donald = "duck" ; public String getText() { return donald ; } void setText(String donald) { this.donald = donald ; } } class ExampleWithUndo = Undo extends Example {}
In the instantiation no constructors are specified for the new class ExampleWithUndo
(they should be declared between the curly braces) and so, as in Java, it is assumed that
the class has only the default constructor. To obtain a correct instantiation Example
must define the mixin inherited
part by implementing the methods getText
and setText
. These methods must have the same return and arguments type and
equivalent throws
clause w.r.t. the corresponding inherited
declaration. The classes obtained by instantiating the mixin provide, in addition to the
methods getText
(inherited from parent class) and setText
(inherited and overridden), all other fields and methods of the class Example
and the donald
. The expected semantics of mixin instantiation can be
informally expressed by the following copy principle:
A class obtained instantiating a mixin M on a parent class P should have the same behavior as a usual heir of P whose body contains a copy of all the components defined in M. |
A class implementing the mixin inherited
part can nevertheless be an
invalid parent for instantiation, since there is another requirement to be met: the heir
class obtained instantiating the mixin must be a correct Java heir class. This leads to a
set of constraints which are described in detail in the article.
What we have seen so far shows the use of a mixin declaration as a scheme, that is, a parametric heir class that can be instantiated on different classes. In this way we avoid code duplication, a good result in itself, but Jam allows something more: a mixin can be used as a type and a mixin instance a class obtained instantiating a mixin, to be not confused with an is a subtype of both the mixin and the parent class on which it has been instantiated. This allows the programmer to manipulate objects of any mixin instance by using the common interface specified by the mixin declaration. An important consequence is that Jam supports a programming style (sometimes called mixin-based) where different ingredients are "mixed" together in defining a class. This paradigm has been advocated on the methodological side since it allows to partly recover the expressive power of multiple inheritance without introducing its complication; however the novelty of Jam is that mixin-based programming is rigorously introduced in the context of a strongly typed language.
Jam is an upward-compatible extension of Java 1.0 (apart from two new keywords), a
great effort has been spent in integrating mixin-related features with the Java overall
design principles, the type system is a natural extension of the Java type system with a
new kind of types (mixin types), the dynamic semantics is directly defined by translation
into Java and, finally, this translation has been implemented by a Jam to Java translator
which makes Jam immediately executable on every Java Virtual Machine. The implementation
of the Jam to Java translation is called jamc
(Jam compiler); it is a command
line utility which is used in the same way as an ordinary compiler, that is, it takes as
arguments a sequence of Jam files (extension .jam
) and produces a set of Java
files. Since jamc
has been implemented in Java, clearly the corresponding
command invokes a script, rather than a real executable file, which makes the Java Virtual
Machine (JVM) load and execute the class file which implements jamc
.
Jam - A Smooth Extension of Java with Mixins (short version) by D.Ancona, G.Lagorio and E.Zucca; ECOOP'00, LNCS, Springer Verlag, 2000 (DISI-TR-99-15) as gzipped-postscript | |
Jam - A Smooth Extension of Java with Mixins (extended version) by the same authors as technical report submitted for journal publication gzipped-postscript. |
A Jam to Java translator has been implemented in Java 1.1 (note that Jam is an
extension of Java 1.0, but its compiler was written using Java 1.1).
It is available as a ZIP archive containing the compiled version and the sources.
v1.05 (693k) | |
LALR Grammar (35k - this file is also contained in the whole package) |
Please send any suggestion to lagorio@disi.unige.it
(last update: 6th March 2002)