首页 > 解决方案 > 在 Scala 中利用泛型返回类型

问题描述

所以我想使用一个通用的返回类型,并能够在函数中使用该类型的信息。不确定这是可能的,但这是我想要的:

  def getStuff[A](a: MyObj, b: String): Option[A] = {
    // do some stuff
    A match {
      case String => Some(a.getString(b))
      case Integer => Some(a.getInt(b))
      ...
      case _ => None
    }
  }

但是,如您所知,A match这是不可能的。关于如何实现这一目标的任何想法?

标签: scalagenericspolymorphismpattern-matching

解决方案


这是使用类型类的经典案例:

trait StuffGetter[T] { // typeclass
  def get(obj: MyObj, s: String): Option[T]
}  

implicit val stringGetter = new StuffGetter[String] {
   def get(o: MyObj, s: String): Option[String] = ???
}
implicit val intGetter = new StuffGetter[Int] {
   def get(o: MyObj, s: String): Option[Int] = ???
}

def getStuff[A](a: MyObj, b: String)(implicit ev: StuffGetter[A]): Option[A] =
  ev.get(a, b)

val stuff0 = getStuff[String](obj, "Hello")  // calls get on stringGetter
val stuff1 = getStuff[Int](obj, "World") // call get on intGetter
val stuff2 = getStuff[Boolean](obj, "!") // Compile-time error

StuffGettertrait 定义了您想要对泛型类型执行的操作,并且该 trait 的每个值implicit都提供了特定类型的实现。(对于自定义类型,这些通常放置在该类型的伴随对象中;编译器将在那里查找它们)

getStuff被调用时,编译器将寻找具有匹配类型的implicit实例。StuffGetter如果不存在这样的实例,这将失败,否则将在ev参数中传递。

这样做的好处是“匹配”是在编译时完成的,并且在编译时也会检测到不支持的类型。


推荐阅读