所以我想使用泛型回傳型別并能夠在函式中使用該型別的資訊。不確定這是可能的,但這是我想要的:
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這不是一種可能性。關于如何實作這一目標的任何想法?
uj5u.com熱心網友回復:
這是使用型別類的經典案例:
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
該StuffGetter特性定義的操作要對泛型型別執行,且每個implicit該性狀值提供特定型別的實作。(對于自定義型別,這些通常放在型別的伴隨物件中;編譯器會在那里尋找它們)
當getStuff被呼叫時,編譯器將查找具有匹配型別的implicit實體StuffGetter。如果不存在這樣的實體,這將失敗,否則將在ev引數中傳遞。
這樣做的好處是“匹配”是在編譯時完成的,并且在編譯時也會檢測到不受支持的型別。
uj5u.com熱心網友回復:
從概念上講,我們可以在運行時區分模式匹配,它看起來像這樣
def getStuff[A](...) =
A match {
...
}
和編譯時的模式匹配,看起來像這樣
def getStuff[A](...)(implicit ev: Foo[A]) = {
ev.bar(...)
}
要理解的關鍵概念是型別在運行時不存在,因為它們在編譯后被“擦除”,因此一旦程式運行,就沒有足夠的資訊來對型別進行模式匹配。然而在編譯時,也就是在程式運行之前,型別確實存在并且 Scala 提供了要求編譯器通過隱式/給定機制對它們進行有效模式匹配的方法,看起來像這樣
// type class requirements for type A
trait StringConverter[A] {
def getOptValue(b: String): Option[A]
}
// evidence which types satisfy the type class
implicit val intStringConverter: StringConverter[Int] = (b: String) => b.toIntOption
implicit val strStringConverter: StringConverter[String] = (b: String) => Some(b)
implicit def anyStringConverter[A]: StringConverter[A] = (b: String) => None
// compile-time pattern matching on type A
def getStuff[A](b: String)(implicit ev: StringConverter[A]): Option[A] = {
ev.getOptValue(b)
}
getStuff[Int]("3") // : Option[Int] = Some(value = 3)
getStuff[String]("3") // : Option[String] = Some(value = "3")
getStuff[Double]("3") // : Option[Double] = None
這種編譯時模式匹配稱為型別類模式。
理解型別和類之間的區別是 Scala 的基本概念之一https://docs.scala-lang.org/tutorials/FAQ/index.html#whats-the-difference-between-types-and-classes和 gorking它將有助于理解如何撰寫型別類。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/339691.html
