Jumbo

Computer Science Department
University of Illinois at Urbana-Champaign

Jumbo Examples

Traits

This paper by Scharli, Ducasse, Nierstrasz, and Black introduced the idea of traits, "composable units of behavior" encapsulating methods, but not states, that describe behaviors that should be common across many classes. They are designed to reduce code duplication, being especially useful in situations where the class hierarchy prevents using inheritance for code reuse.

One of the defining factors of traits is that they can be flattened; a class with added traits should behave exactly as though the methods were written in the class itself. This clearly leads to a straightforward implementation in Jumbo.

Two main classes were used to implement traits in Jumbo.

The TraitMethod class keeps track of each method that could be added to a trait, what that method's name is, and what other functions that method requires. New trait methods are defined by extending this class and defining the getCode function to return the code of the method.

The Trait class keeps a set of TraitMethods, and has functions to rename methods and compose traits.

Renaming a method in a trait in Jumbo is a simple matter of finding the method in that trait with the given name, and changing its name to match the new one. Composing traits is similarly easy: unify the method sets of each trait, and annihilate methods with conflicting names (as described in the paper).

Using a trait in a generated class in Jumbo requires calling the GetCode() function of the Trait. At this point, the Trait will generate code for each of its methods, using the name currently mapped to that method, and return a MonoList of Code containing all the methods generated. MonoLists of Code are the datatype used in Jumbo to represent class bodies; the list returned by the Trait can therefore be appended to the existing body of a class to be generated. This necessitates that the class utilizing the trait define its body as a MonoList of Code; the list of code from the trait cannot be spliced in later. For now, a TraitUser class has been defined that allows method and state variable code to be added to a MonoList, to be used as the basis for a class utilizing Traits.

One thing about the structure of Jumbo causes some issues in the implementation of traits. Jumbo does not allow inspection of quoted code values. This is why the code for the methods of a trait is not generated until the getCode() function is called; there would be no way to rename a method that had been already generated. The inability to inspect quoted code also means that the only way to determine whether a class a particular trait is being plugged into meets that trait's requirements is to either attempt to compile it and see if it produces errors, or to use a wrapper class (similar to the Traits and TraitMethods) keeping track of what methods the class can provide to traits it utilizes. The latter method, however, complicates the process of creating a trait-using class, and still has issues with determining the methods provided to the class through inheritance; therefore, we have opted to allow the compiler to catch any issues where a trait is used with an unmet requirement. Finally, our inability to determine what methods are already defined in a class into which we are inserting trait code means that we cannot fulfill one of the specifications of traits; namely, that they are overridden by methods defined in the class itself.

Download the Jumbo Trait test code!

    Last updated on Wed Aug 17 22:30:01 CDT 2005 .