Lex Spoon wrote:
Wasn't there a big collections refactoring done with traits? I have been meaning to dig it up and read through it, but have never found the time.
This was one of the academic exercises I was referring to, see here:
http://citeseer.ist.psu.edu/581397.html
Also, its main focus was on squeezing entropy out of the system (i.e., eliminate code duplication) not necessarily improvements in design (the paper claims some but I'm pretty sure that *any* serious bit of refactoring of a 20 year old class hierarchy could improve a few things ;-)
Here's one use of them, though, that I use all the time in Scala's variation on traits. You can make Squeak's Magnitude be a trait instead of an abstract class. That is, given a < method, which is abstract in Magnitude, you can have Magnitude define all the other methods for you.
How interesting. Does Scala use traits extensively?
Or closer to your heart, Andreas, how would you like to have a Rectangular trait for all those #left, #right, #topLeft, etc. methods? It would require a #rectangle method, which for Rectangle is "yourself" and for Morph is "bounds". Then all these helper methods would get defined for you by the trait.
Did I mention toy examples before? ;-) Yes, that is one of those. Unfortunately, in real code I only ever have that problem in about a single base class so it's usually not worth creating an extra entity (trait). In addition, I have found that I prefer to carefully choose which parts of the interface to expose and which ones not - Players in Tweak expose a partial set of rectangle operations, a partial set of collection operations but not both to the full extent simply because that would be crazy overload. Where I need the full interface I prefer aspects so that if you really really need #squishedWithin: you say "player bounds squishedWithin: aRectangle" instead. Which gives you the advantage of providing a useful, filtered interface as the default without eliminating access to the full interface. And finally, the rectangle interface is very stable and hardly ever changes so evolution of interfaces isn't really an issue either.
This usage of traits may be small one by one, but they are enough to convince me thre are some very nice uses of traits that are not available in Smalltalk. What they do is take a thin interface and widen it to a rich interface. They let you *define* classes using the thin interface, and *use* them with the rich interface.
So where are these uses? Can you point me to any in real applications?
Anyway, I don't know anything about the Squeak version. My day jobs have kept me too busy to look into Squeak's traits as I would like to. However, I can vouch for the feature, just based on the above examples.
Well, I'm still on the lookout trying to find a really convincing example of use for traits. If you can point me to one (e.g., point me to actual code in an actually running system) I'd really appreciate it.
Cheers, - Andreas