views:

210

answers:

1

I'm working with legacy Java code which returns java.lang.object. I'm passing it into a function and I'd like to do some implicit conversions as such:

implicit def asInt( _in:Option[Object] ) = _in asInstanceOf[ Option[Int] ]
implicit def asDouble( _in:Option[Object] = _in asInstanceOf[ Option[Double] ]

private def parseEntry( _name:String, _items:Map[String,Object] ) = _name match{
    case docName.m_Constants =>
        new Constants( _items get( Constants m_Epsilon ), _items get( Constant m_Rho ),
                       _items get( Constants m_N ) )

Technically it goes on but I keep getting the same errors: expected Int, Option[Object] found. Here, a focused snap-shot of the problem:

private def foo( _items:Map[String,Object] ) ={
    val bar:Option[Int] = _items get( "Bar" ) }

How have I done my implicits wrong? I was hoping it would do the transformation for me instead of me having to write "asInstanceOf" each and every time.

+2  A: 

Your implicit conversion does not apply, because your implicit conversion will convert Option[Object] to Option[Int], but it appears your code is expecting it to convert Object to Option[Int].

Try wrapping _items get( "Bar" ) with Some() to get an Option[Object] instead of just an Object and see if your implicit conversion kicks in.

EDIT: Actually, I'm not sure why this doesn't work for you, given that (as you correctly pointed out in your comment), Scala maps return options. The following code works for me and prints "37", as I would expect it to:

import scala.collection.mutable.Map
import scala.collection.mutable.HashMap

object ImplicitConversions {
    implicit def asInt( _in:Option[Object] ) = _in.asInstanceOf[Option[Int]]
    implicit def asDouble( _in:Option[Object] ) = _in.asInstanceOf[Option[Double]]

    private def foo( _items:Map[String,Object] ) = {
        val bar:Option[Int] = _items.get("Bar")
        println(bar.get.intValue)
    }

    def main(args: Array[String]) {
      val map:Map[String,Object] = new HashMap[String, Object]
      map.put("Bar", Integer.valueOf(37))
      foo(map)
    }
}

However, if I use Java maps, then wrapping with Some() works:

import java.util.Map
import java.util.HashMap

object ImplicitConversions {
    implicit def asInt( _in:Option[Object] ) = _in.asInstanceOf[Option[Int]]
    implicit def asDouble( _in:Option[Object] ) = _in.asInstanceOf[Option[Double]]

    private def foo( _items:Map[String,Object] ) = {
        val intermediate = Some(_items.get("Bar"))
        val bar:Option[Int] = intermediate
        println(bar.get.intValue)
    }

    def main(args: Array[String]) {
      val map:Map[String,Object] = new HashMap[String, Object]
      map.put("Bar", Integer.valueOf(37))
      foo(map)
    }
}

(Note that I did have to store the result of Some() in an intermediate variable to get the conversion to work - Perhaps someone more expert in Scala could show me how to avoid that intermediate step. ;-) )

Is it possible that Scala and Java maps are getting mixed up in your code? You did say that you were calling into legacy Java code, which is why you had to do all of this implicit conversion in the first place. If you're using Java maps when you think you're using Scala maps, then that would explain the disconnect here.

Joe Carnahan
But get from Map returns an Option[B], see http://www.scala-lang.org/docu/files/api/scala/collection/Map.html#get%28A%29
wheaties