好吧,所以我不知道这段代码有什么问题:
import scala.reflect.runtime.universe._
trait Key extends Product
case class SomeKey(a: Int, b: String) extends Key
case class SomeOtherKey(a: Int, b: String, c:Boolean) extends Key
trait MyTrait[T <: Key] {
def someField: Int
def someFunc(implicit tTypeTag: TypeTag[T]): Map[T, Int] = {
typeOf(tTypeTag) match {
case t if t =:= typeOf[SomeKey] => Map(SomeKey(1,"2") -> 1)
case t if t =:= typeOf[SomeOtherKey] => Map(SomeOtherKey(1,"2",true) -> 2)
}
}
}
如果从扩展Map[SomeKey, Int]
的案例类中调用someFunc
,我希望(示例已被简化)能够返回MyTrait[SomeKey]
。然后从Map[SomeOtherKey, Int]
MyTrait[SomeOtherKey]
case class MyClass(val s: Int) extends MyTrait[SomeKey] {
override def someField = s
}
这里,MyClass
的新实例在调用Map[SomeKey, Int]
时应返回someFunc
。
但是它甚至无法编译,编译器抱怨模式匹配的每一行:
type mismatch;
found : (Playground.this.SomeKey, Int)
required: (T, Int)
或
type mismatch;
found : (Playground.this.SomeOtherKey, Int)
required: (T, Int)
答案 0 :(得分:4)
这是使用类型类和隐式的解决方案。
trait Key extends Product
case class SomeKey(a: Int, b: String) extends Key
case class SomeOtherKey(a: Int, b: String, c:Boolean) extends Key
trait TypeClass[T] {
def someFunc: Map[T, Int]
}
object TypeClass {
implicit def forSomeKey: TypeClass[SomeKey] = new TypeClass[SomeKey] {
override def someFunc: Map[SomeKey, Int] = Map(SomeKey(1, "2") -> 1)
}
implicit def forSomeOtherKey: TypeClass[SomeOtherKey] = new TypeClass[SomeOtherKey] {
override def someFunc: Map[SomeOtherKey, Int] = Map(SomeOtherKey(1, "2", true) -> 1)
}
}
trait MyTrait[T <: Key] {
def someField: Int
def someFunc(implicit tc: TypeClass[T]): Map[T, Int] = tc.someFunc
}
答案 1 :(得分:3)
TypeTag
会将类型信息转移到运行时,但是方法的返回类型是 compile-time 构造,因此会出现编译器错误。而是考虑通过扩展方法(但又被Luis的建议劫持了)
sealed trait Key
final case class SomeKey(a: Int, b: String) extends Key
final case class SomeOtherKey(a: Int, b: String, c: Boolean) extends Key
trait MyTrait[T <: Key]
trait KeyFactory[T <: Key] {
def someFunc(): Map[T, Int]
}
object KeyFactory {
def someFunc[T <: Key](implicit ev: KeyFactory[T]) = ev.someFunc
implicit val someKeyFoo: KeyFactory[SomeKey] = () => Map(SomeKey(1,"2") -> 1)
implicit val someOtherKey: KeyFactory[SomeOtherKey] = () => Map(SomeOtherKey(1,"2", true) -> 2)
}
implicit final class MyTraitKeyFactory[T <: Key : KeyFactory](private val v: MyTrait[T]) {
def someFunc(): Map[T, Int] = implicitly[KeyFactory[T]].someFunc()
}
case class MyClass(s: Int) extends MyTrait[SomeKey]
case class MyOtherClass(s: Int) extends MyTrait[SomeOtherKey]
MyOtherClass(42).someFunc()
MyClass(11).someFunc()
输出
res0: Map[SomeOtherKey,Int] = Map(SomeOtherKey(1,2,true) -> 2)
res1: Map[SomeKey,Int] = Map(SomeKey(1,2) -> 1)