我试图了解泛型如何在Scala中与继承一起工作。我有以下代码:
sealed trait Model {}
case class Model1() extends Model
case class Model2() extends Model
trait Repo[A <: Model] {
def doSomething(model: A)
}
class Repo1 extends Repo[Model1] {
override def doSomething(model: Model1): Unit = {
println("Model 1")
}
}
class Repo2 extends Repo[Model2] {
override def doSomething(model: Model2): Unit = {
println("Model 2")
}
}
object Play extends App {
def getModel(i: Int): Model =
i match {
case 1 => Model1()
case 2 => Model2()
case _ => throw new RuntimeException("model not found")
}
val model = getModel(1)
val repo = model match {
case _: Model1 => new Repo1
case _: Model2 => new Repo2
case _ => throw new RuntimeException("something went wrong")
}
repo.doSomething(model)
}
在最后一行repo.doSomething(model)
我得到Type mismatch. Required: _.$1 Found: Model
根据此答案,在Scala中使用泛型实现特征的正确方法是什么?如果我的repos类使用该类型扩展了特征应该起作用。
我是Scala的新手,正在尝试围绕类型系统,泛型,隐式,上限/下限...
什么是_.$1
类型,我该如何做?谢谢!
scala是静态类型的,其值model
是编译时间类型Model
和repo
编译时间类型的Repo
因此repo.doSomething
没有进一步完善。的签名doSomething
说它将接受Model
参数的某些子类型,但我们不知道是哪个子类型,换句话说,编译器不知道的类型model
和repo
align 的类型。
为了使它们对齐,您有几种选择。
val castRepo = repo.asInstanceOf[Repo[Any]]
这样就关闭了安全性,您告诉scala“相信我,我知道我在做什么”。当您知道自己在做什么时,这在某种程度上是可以的,但是真正知道自己在做什么的人往往不相信自己比编译器更了解自己,因此保留类型安全性的另一种解决方案可能会更好。
例如,您可以创建包装类型
case class Aligned[A <: Model](model: A, repo: Repo[A]) {
def doIt = repo.doSomething(model)
}
val aligned = model match {
case m: Model1 => Aligned(m, new Repo1)
case m: Model2 => Aligned(m, new Repo2)
case _ => throw new RuntimeException("something went wrong")
}
aligned.doIt
在Aligned
,scalac知道Model
类型和Repo
类型排列。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句