The Artima Developer Community
Sponsored Link

Computing Thoughts
Mixins: Something Else You Can't Do With Java Generics?
by Bruce Eckel
October 20, 2005
Summary
The paper "A First-Class Approach to Genericity" introduces the idea of the mixin, which seems to be quite a powerful concept, and then shows that you can't do it with Java generics. I wonder if anyone has any alternative approaches to this problem.

Advertisement

Here's the link to the paper (PDF).

(Also see the follow-on to this article, Mixins 2.

The term mixin seems to have acquired numerous meanings over time, but the fundamental concept is that of mixing in capabilities in the same way that you would mix adornments like cookies and candy pieces into ice cream. Although these things are reasonably well-blended, you can still see evidence of their having been mixed in. More importantly, it's something you do at the last minute, which makes it convenient to easily assemble classes.

One value for mixins is that they consistently apply characteristics and behaviors across multiple classes.

When you look at the way that it is used, the concept of a mixin seems very closely related to the Decorator design pattern. Something is decoratable, and you layer on functionality by wrapping other classes around the decoratable. Decorators, however, are implemented using composition and formal structures (the decoratable/decorator hierarchy), whereas mixins are inheritance-based. So you could think of parameterized-type-based mixins as a generic decorator mechanism that does not require the inheritance structure of the Decorator design pattern.

Because the resulting class contains all the methods of interest just like any other class, the mixin approach is arguably more natural than a decorator, because the type of the object that results from using decorators is the last type that it was decorated with, whereas the type of the mixin is all the types that have been mixed together.

One of the strongest arguments made for multiple inheritance in C++ is for the use of mixins. However, a more interesting and elegant approach to mixins is using parameterized types, whereby a mixin is a class that inherits from its type parameter. In C++, you can easily create mixins because C++ remembers the type of its template parameters.

Here's a C++ example with two mixin types: one that allows you to mix in the property of having a time stamp, and another that mixes in a serial number for each object instance:


//: generics/Mixins.cpp
#include <string>
#include <ctime>
#include <iostream>
using namespace std;

template<class T> class TimeStamped : public T {
  long timeStamp;
public:
  TimeStamped() { timeStamp = time(0); }
  long getStamp() { return timeStamp; }
};

template<class T> class SerialNumbered : public T {
  long serialNumber;
  static long counter;
public:
  SerialNumbered() { serialNumber = counter++; }
  long getSerialNumber() { return serialNumber; }
};

// Define and initialize the static storage:
template<class T> long SerialNumbered<T>::counter = 1;

int main() {
  TimeStamped<SerialNumbered<string> > mixin1, mixin2;
  mixin1.append("test string 1"); // A string method
  mixin2.append("test string 2");
  cout << mixin1 << " " << mixin1.getStamp() << " " <<
    mixin1.getSerialNumber() << endl;
  cout << mixin2 << " " << mixin2.getStamp() << " " <<
    mixin2.getSerialNumber() << endl;
} /* Output: (Sample)
test string 1 1129775318 1
test string 2 1129775318 2
*///:~

Notice that the resulting type has all the methods of the mixed-in types. You can think of a mixin as a function that maps existing classes to new subclasses.

Unfortunately, Java generics don't permit this. Erasure forgets the base-class type, so a generic class cannot inherit from one of its generic parameters.


//: generics/Mixins.java
// {CompileTimeError}
import java.util.*;

// Can't inherit from a generic parameter:
public class TimeStamped<T> extends T {
  public final long timeStamp;
  TimeStamped() {
    timeStamp = new Date().getTime();
  }
}

public class SerialNumbered<T> extends T {
  private static long counter = 1;
  public final long serialNumber = counter++;
}

public class Mixins {
  public static void main(String[] args) {
    SerialNumbered<TimeStamped<String>> mixin = 
      new SerialNumbered<TimeStamped<String>>();
  }
} ///:~

So here's the question: is there some other way to perform something that produces this kind of mixin cleverness, or has erasure again foiled us?

Talk Back!

Have an opinion? Readers have already posted 27 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Bruce Eckel adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Bruce Eckel (www.BruceEckel.com) provides development assistance in Python with user interfaces in Flex. He is the author of Thinking in Java (Prentice-Hall, 1998, 2nd Edition, 2000, 3rd Edition, 2003, 4th Edition, 2005), the Hands-On Java Seminar CD ROM (available on the Web site), Thinking in C++ (PH 1995; 2nd edition 2000, Volume 2 with Chuck Allison, 2003), C++ Inside & Out (Osborne/McGraw-Hill 1993), among others. He's given hundreds of presentations throughout the world, published over 150 articles in numerous magazines, was a founding member of the ANSI/ISO C++ committee and speaks regularly at conferences.

This weblog entry is Copyright © 2005 Bruce Eckel. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use