Wednesday, July 29, 2009

Unchecked Ducktyping in Scala

I finally had an occasion to to use Scala's structured typing, although not in the way it was intended. I needed to call a method on a class that was compiled during runtime. Therefore I had no type information on it. So I cast it to a structural type.

Here is something you can try that illustrates the principal:

scala> val o:AnyRef = "hi"
o: AnyRef = hi

scala> o.asInstanceOf[ { def length():Int } ].length()
res2: Int = 2

I obviously didn't come up with this strategy myself, but look at how much nicer this is than that the alternative using java reflection to invoke the method.

One question though: Is there a way to check if the object fits the type before casting? For example I would love to do:

if( o.getClass.isAssignableFrom( { def length():Int } ) {
// do something

Right now the only way I know is to cast the object to the structural type then test each method for existance. Not that convenient.


federico silva said...

One whishes we could do;
o.isInstanceOf[ { def length():Int } ]
which evals to true but
o.isInstanceOf[ { def color():Int } ]
evals as true, too.

The compiler warns that:
warning: refinement AnyRef{def color(): Int} in type is unchecked since it is eliminated by erasure.

Erasure stinks.

Paul said...

See for the status of this.