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.

An example

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.


The Jam to Java translator

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.


Downloads

 

Papers

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.

 

Implementation

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)