Generics Scala默认类型标签

Generics Scala默认类型标签,generics,default,option,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[

我在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(val)
输出为“列表选项”,无论它是选项[List[Any]]还是选项[String]

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

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

def foo[T](bar: Any)(implicit tt: TypeTag[T])
因此,您可以提供默认值:

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

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

这意味着,如果不显式地添加类型,编译器将推断出
无任何内容
,因为它没有进一步的信息

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.reflect.runtime.universe_
def foo[T:TypeTag](条:任意)={
酒吧比赛{
案例选项:选项[T]=>选项匹配{
如果typeOf[T]=:=typeOf[Nothing]=>println(“Nothing”),则情况x
如果[T]println的类型(“列表选项”)为第十种情况
案例x如果[T]println的类型(“映射选项”)
如果[T]println的类型(“布尔选项”)为第x种情况
大小写=println(“字符串”)
}
案例=>println(“无选项”)
}
}

我说“改进”是因为人们永远不应该写这样的代码。感觉好像它试图将非类型语言中的一些习惯用法硬塞进Scala中。

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

我写了另一个函数。 现在,如果我需要类型标签,我可以使用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")
  }
}
def foo(条形图:任意)={
fooType[字符串](条形)
}
def FootType[T:TypeTag](条形图:任意)={
酒吧比赛{
案例选项:选项[T]=>选项匹配{
如果[T]println的类型(“列表选项”)为第十种情况
案例x如果[T]println的类型(“映射选项”)
如果[T]println的类型(“布尔选项”)为第x种情况
大小写=println(“字符串”)
}
案例=>println(“无选项”)
}
}

真的,不要这样写代码。甚至不像我的“解决方案”。
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")
  }
}