Infrequently updated blog!

Things Calum may be responsible for

Better classing through Scala

Sunday, 16 March 2008

Rather than the promised follow-up to my last post (it's coming, honest), I'm just going to update the way that I did the first section of that post. I realised earlier that rather than making my hastily-constructed RichIterable a class, I should have made it a trait. In this way, other classes can use its functionality explicitly if they know about it and, critically, can override the functionality in a way that makes more sense to them.

To do this and still be able to do the implicit cast thing I showed, we also need a concrete class to mix the trait in with. Since you can't (as far as I know) mix in traits after you've created an object, if we just create a wrapper class for Iterable objects:

class IterableWrapper[A]( underlying: Iterable[A] ) extends Iterable[A]
{
  override def elements = underlying.elements
}

Which means we can now express the implicit function from before as so, creating a new wrapper with our trait mixed in:

implicit def iterable2RichIterable[A]( iterable: Iterable[A]) = {
  new IterableWrapper( iterable ) with RichIterable[A]
}

This means that any other collection can just extend the RichIterable trait if they don't want to require the type conversion to use the new methods, or if they want to replace the functions with better implementations. Our actual RichIterable trait can be a subtrait of Iterable, too, meaning less indirection. It's wonderful I tells ya.

The extra curly brackets here do absolutely nothing; I just feel it's clearer to add them in if an expression like this one is too long to fit on a line.

Labels: ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home