How save a TypeTag and then use it later to reattach the type to an Any (Scala 2.10)

丶灬走出姿态 提交于 2019-11-30 15:16:40

Here is my own answer:

I don't need TypeTags and I don't really need a keyed type or a tuple. Just simple generics seems to do. I don't need a match & case classes enumerating the possible values for Any. Just a simple map of name-value pairs. I then access it using

hmap.get Float .... println( "Get 'pi'=" + x * 2 )

It seems reasonable and very readable to just invoke: hmap.get Float . The types are not checked at compile time and so I will get runtime errors if I ask for the wrong type. If I do decide to filter the types there is a place to do it. I should check for castability and let Option return None if it can't be done and not Exception as it does now.

To me the above is neater & reads nicer than casting later since all the error handling can be in the get rather than using :

hmap.get("pi").asInstanceOf[Float].

Thanks for your help!

Here is the simpler code now:

 import collection.mutable.Map

object Test extends HMap {

  def main( args: Array[ String ] ) {

    var hmap = new HMap
    hmap( "anInt" ) = 1
    hmap( "pi" ) = 3.1416f
    hmap( "c" ) = "hello"
    // Test
    val result = hmap.get[ Float]( "pi" )
    result match {
      case Some( x ) =>
        println( "Get 'pi'=" + x * 2 )
      case _ => println("Not found")
    }
  }
}

class HMap {
  private var coreMap =
    Map.empty[ String, Any ]

  // Save the key with the value
  def update[ T ]( key: String, value: T ) =
    coreMap.put( key, value )

  def get[ T ]( key: String ): Option[ T ] = {
    val option = coreMap.get( key )
    option match {
      case None      => None
      case Some( x ) => Some( x.asInstanceOf[ T ] )
    }
  }
}

T is defined when you call the method get, you cant change it inside a function to another type. Compiler need information to get type information for T or you have to provide it explicitly:

def get[T](key: String) = m.get(key).map(_.asInstanceOf[T])
get[Int]("anInt")

If a key is typed, then T can be inferred:

class Key[T](name: String)
def get[T](key: Key[T]) = ...
get(Key[Int]("anInt"))

To check the type is correct when getting from map you can do what you did originally, save a type and a value:

val m = Map.empty[String, (Type, Any)]

def put[T: TypeTag](key: String, value: T) = m.put(key, (typeOf[T], value))

def get[T: TypeTag](key: String) = m.get(key) match {
    case Some((t, v)) if t =:= typeOf[T] => Some(v.asInstanceOf[T])
    case _ => None
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!