Scala默认TypeTag

时间:2014-09-17 09:04:53

标签: generics default option

我在Scala中使用typetags来匹配选项

def foo[T: TypeTag](bar: Any) = {
  bar match {
    case option: Option[T] => option match {
      case x if typeOf[T] <:< typeOf[List[Any]] => println("List Option")
      case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
      case x if typeOf[T] <:< typeOf[Boolean] => println("Boolean Option")
      case _ => println("String")
    }
    case _ => println("no Option")
  }
}

所以当我以这种方式使用这个功能时

foo[List[Any]](val)

一切都会好,在这种情况下输出是“列表选项”。 但是当我尝试在没有TypeTag

的情况下使用它时
foo(val)

输出为“列表选项”,无论是[Option [Any]]还是Option [String]。

所以现在我的问题: 是否可以为我的TypeTag T定义默认值? 如果不需要TypeTag,我想使用我的函数,然后输出应该是“String”而不是“List Option”。 可以为参数定义默认值,因此可能也适用于TypeTag。

3 个答案:

答案 0 :(得分:1)

您的问题是T类型与参数bar的类型无关。

这意味着,如果您未明确添加类型,编译器将推断Nothing,因为它没有进一步的信息。

Nothing是所有内容的子类型,因此您的子类型检查已经在第一个分支中成功(实际上所有情况都适用于Nothing)。

您的代码可以像这样“改进”:

import scala.reflect.runtime.universe._
def foo[T: TypeTag](bar: Any) = {
  bar match {
    case option: Option[T] => option match {
      case x if typeOf[T] =:= typeOf[Nothing]       => println("Nothing")
      case x if typeOf[T] <:< typeOf[List[Any]]     => println("List Option")
      case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
      case x if typeOf[T] <:< typeOf[Boolean]       => println("Boolean Option")
      case _ => println("String")
    }
    case _ => println("no Option")
  }
}

我说“改进”因为永远不应该写这样的代码。感觉它试图将一些成语从无类型语言中剔除到Scala中。

答案 1 :(得分:0)

def foo[T: TypeTag](bar: Any)

只是

def foo[T](bar: Any)(implicit tt: TypeTag[T])

因此,您可以提供默认值:

def foo[T](bar: Any)(implicit tt: TypeTag[T]=...)

答案 2 :(得分:0)

最简单的方法是解决方案。

我写了另一个函数。 现在,如果我需要TypeTags,我可以使用fooType,否则我可以使用foo。

def foo(bar: Any) = {
  fooType[String](bar)
}

def fooType[T: TypeTag](bar: Any) = {
  bar match {
    case option: Option[T] => option match {
      case x if typeOf[T] <:< typeOf[List[Any]] => println("List Option")
      case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
      case x if typeOf[T] <:< typeOf[Boolean] => println("Boolean Option")
      case _ => println("String")
    }
    case _ => println("no Option")
  }
}