本文介绍了如何保存 TypeTag,然后稍后使用它将类型重新附加到 Any (Scala 2.10)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我正在尝试制作自定义的异构列表和地图.尽管有使用 Manifest 的示例,但在 Scala 2.10 中它们已被弃用,我应该使用 TypeTags(或 Classtags).在地图的情况下,我似乎可以使用(比如说)元组 String->(TypeTag[ _ <: Any ], Any ) 来保留 Any 与 Type 的绑定.

I am trying to make custom heterogeneous lists and maps. Although there are examples around using Manifest, with Scala 2.10 they are deprecated and I should use TypeTags (or Classtags). In the case of maps it seems I can preserve the binding of an Any to a Type using (say) a tuple String->(TypeTag[ _ <: Any ], Any ).

我的问题是如何从恢复的 TypeTag 和未定义的 T 中获取,以便能够返回 TypeTag.tpe 的实例 - 在代码中我有//** 这里如何使用保存的 typeTag 定义 T?**

My problem is how to get from the recovered TypeTag and an undefined T, to be able to return an instance of TypeTag.tpe - at the point in the code where I have //** How do I use saved typeTag to define T here?**

正如所写,方法 get 中没有编译器错误,但 T 设置为 Nothing 并返回 Some(Nothing).我希望我注释掉的行能够工作:case Some( x ) =>//println( "Get 2*'pi'=" + x*2 ) 其中有一个编译器消息,value * 不是 Nothing 的成员".我意识到我可以写得更紧凑,但完成后,我可以将鼠标悬停在我的 IDE 中并一步一步地进行.有一个相关的问题 - Scala:什么是 TypeTag,我该如何使用它? 但它似乎没有走到最后一英里" - 重新标记 Any.

As written, there are no compiler errors in method get, but T is set to Nothing and returns Some(Nothing). I would like my commented-out line to work: case Some( x ) => // println( "Get 2*'pi'=" + x*2 ) where there is a complier message, "value * is not a member of Nothing".I realise I could write more compactly, but as done, I can mouse-over in my IDE and follow step by step. There is a related question - Scala: What is a TypeTag and how do I use it? but it does not seem to go the 'last mile' - retagging an Any.

如何做到这一点?

这是我到目前为止的代码:

Here is the code I have so far:

import scala.reflect._
import scala.reflect.runtime.universe._
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( "pi" )
    result match {
      case Some( x ) =>
        println( "Get 'pi'=" + x*2 )
      case _ =>
    }
  }
}

class HMap {
  private var coreMap =
    Map.empty[ String, ( TypeTag[ _ <: Any ], Any ) ]

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

  override def toString = coreMap.toString

  def get[ T: TypeTag ]( key: String ): Option[ T ] = {
    val option = coreMap.get( key )
    val result = option match {
      case None => None
      case Some( x ) => {
        val typeTag = x._1; val value = x._2
        println( "Matched Type = " +
            typeTag.tpe + "   Value=" + value )
        // **** How do I use saved typeTag to define T here? ****
        val v = value.asInstanceOf[ T ]
        val s = Some( v )
        println( "Returning " + s )
        s
      }
    }
    result
  }
}

推荐答案

T 是在调用 get 方法时定义的,不能在函数内部将其更改为其他类型.编译器需要信息来获取 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")

如果键入一个键,则可以推断出 T:

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
}

这篇关于如何保存 TypeTag,然后稍后使用它将类型重新附加到 Any (Scala 2.10)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 22:26