Implicit Conversions: Scala's Type Safe Answer To Ruby's Open Class
April 17, 2009
Let's say that you are writing an application that squares things often, so you would like to be able to do this:
>> 4.squared
=> 16
In Ruby, that's easy-peasy:
class Integer
def squared
self * self
end
end
Wham. Done. Open it right up, shove your method in there and you are bending the language to your will. But what if you couldn't modify existing classes? Maybe you would do this:
class IntegerWrapper
def initialize(value)
@value = value
end
def squared
@value * @value
end
end
Cool. Now you haven't modified Integer, but you get the same effect. So you just use it like this:
>> IntegerWrapper.new(4).squared
=> 16
WOAH! WTF? That is a lot of extra syntax. Having all to call wrapper classes like this really makes it too verbose. So now we shift gears into Scala mode:
scala> class IntegerWrapper(val value : Int) { def squared = value * value }
defined class IntegerWrapper
scala> new IntegerWrapper(4).squared
res0: Int = 16
As you can see on the first line, we define the same IntegerWrapper class. Then we use it just the same way we do in Ruby. But now we throw in an implicit conversion to make the syntactic magic happen:
scala> implicit def wrapInt(i:Int) = new IntegerWrapper(i)
wrapInt: (Int)IntegerWrapper
scala> 4.squared
res1: Int = 16
The implicit def defines an implicit conversion from an Int to an IntegerWrapper. This is our way to tell scala that if we try to call squared on an Int, use this function to convert the Int to an IntegerWrapper for me. Now as you can see, we can call squared on what appears to be a Int, and get the same syntactic advantage of adding methods to existing classes, without really modifying existing classes.