Scala在使用隐式类型时无法访问getter方法-class(变体+多态)
Scala cannot access getter methods when using implicit type-class (variance + polymorphism)
在下面的示例中,我不明白为什么我无法访问 M1
、M2
、M3
classes 上的 getter 方法.
我需要特征 S
与 T
协变才能实现 runSeq
方法。因此,toto
方法需要将 U
作为 T
的超级 class。当我这样做时,我无法再访问参数 t
的构造函数字段。
如果我删除协方差要求 (+T
) 一切正常,但我不知道如何实现 runSeq
方法(特别是它需要接收隐式类型-class 目的)。
abstract class M
case class M1(s: String) extends M
case class M2(i: Int) extends M
case class M3(b: Boolean) extends M
trait S[+T] {
def follow(s: String): String
def toto[U >: T](t: U): String
}
implicit object S1 extends S[M1] {
val m1 = M1("1") // this is for testing only
def follow(s: String): String = s + ".M1." + toto(m1)
def toto[M1](t: M1): String = "toto" + t.s // ERROR: cannot resolve "s"
}
implicit object S2 extends S[M2] {
val m2 = M2(2) // for testing purposes only
def follow(s: String): String = s + ".M2." + toto(m2)
def toto[M2](t: M2): String = "toto" + t.i.toString // ERROR: cannot resolve "i"
}
implicit object S3 extends S[M3] {
val m3 = M3(true) // for testing purposes
def follow(s: String): String = s + ".M3." + toto(m3)
def toto[M3](t: M3): String = "toto" + t.b.toString // ERROR: cannot resolve "b"
}
def run[T: S](s: String): String = implicitly[S[T]].follow(s)
run[M1]("run")
def runSeq(seq: S[M]*)(s: String) =
seq.foldLeft(s)((st, tg) => run(st)(tg))
runSeq(S3,S2,S1)("runSeq")
您正在使用类型参数进行遮蔽(例如 M1
与 def toto[M1](t: M1): String = "toto" + t.s
)。
考虑 trait S[+T] { ... def toto[U >: T](t: U): String }
object S1 extends S[M1]
,一个合规的 toto
应该如下实施。
def toto[U >: M1](t: U): String = "toto" + t.s
在这种情况下,对于 U >: M1
,类型系统无法证明 t
被定义为 s: String
。
The type constraints and variance seems wrong there.
首先,请注意 def toto[U >: T](t: U): String
与 def toto(t: Any): String
基本相同,因为 Any
满足任何可能的 T
的界限。这也解释了为什么您无法访问 t
中 T
的成员。请注意,方差与此无关。
T is only covariant because runSeq needs to take a sequence of S[T] with various types of T derived from M. Is there a better way of doing that?
def runSeq(seq: S[_ <: M]*)
直接对应这个。但是,您可能 运行 陷入类型擦除问题:给定一个 S[_ <: M]
,您无法知道它的实际类型参数或检查 M
是否是合适的类型。查找 ClassTag
和 TypeTag
以获取解决方案。同样,这是一个独立于方差的问题。
在下面的示例中,我不明白为什么我无法访问 M1
、M2
、M3
classes 上的 getter 方法.
我需要特征 S
与 T
协变才能实现 runSeq
方法。因此,toto
方法需要将 U
作为 T
的超级 class。当我这样做时,我无法再访问参数 t
的构造函数字段。
如果我删除协方差要求 (+T
) 一切正常,但我不知道如何实现 runSeq
方法(特别是它需要接收隐式类型-class 目的)。
abstract class M
case class M1(s: String) extends M
case class M2(i: Int) extends M
case class M3(b: Boolean) extends M
trait S[+T] {
def follow(s: String): String
def toto[U >: T](t: U): String
}
implicit object S1 extends S[M1] {
val m1 = M1("1") // this is for testing only
def follow(s: String): String = s + ".M1." + toto(m1)
def toto[M1](t: M1): String = "toto" + t.s // ERROR: cannot resolve "s"
}
implicit object S2 extends S[M2] {
val m2 = M2(2) // for testing purposes only
def follow(s: String): String = s + ".M2." + toto(m2)
def toto[M2](t: M2): String = "toto" + t.i.toString // ERROR: cannot resolve "i"
}
implicit object S3 extends S[M3] {
val m3 = M3(true) // for testing purposes
def follow(s: String): String = s + ".M3." + toto(m3)
def toto[M3](t: M3): String = "toto" + t.b.toString // ERROR: cannot resolve "b"
}
def run[T: S](s: String): String = implicitly[S[T]].follow(s)
run[M1]("run")
def runSeq(seq: S[M]*)(s: String) =
seq.foldLeft(s)((st, tg) => run(st)(tg))
runSeq(S3,S2,S1)("runSeq")
您正在使用类型参数进行遮蔽(例如 M1
与 def toto[M1](t: M1): String = "toto" + t.s
)。
考虑 trait S[+T] { ... def toto[U >: T](t: U): String }
object S1 extends S[M1]
,一个合规的 toto
应该如下实施。
def toto[U >: M1](t: U): String = "toto" + t.s
在这种情况下,对于 U >: M1
,类型系统无法证明 t
被定义为 s: String
。
The type constraints and variance seems wrong there.
首先,请注意 def toto[U >: T](t: U): String
与 def toto(t: Any): String
基本相同,因为 Any
满足任何可能的 T
的界限。这也解释了为什么您无法访问 t
中 T
的成员。请注意,方差与此无关。
T is only covariant because runSeq needs to take a sequence of S[T] with various types of T derived from M. Is there a better way of doing that?
def runSeq(seq: S[_ <: M]*)
直接对应这个。但是,您可能 运行 陷入类型擦除问题:给定一个 S[_ <: M]
,您无法知道它的实际类型参数或检查 M
是否是合适的类型。查找 ClassTag
和 TypeTag
以获取解决方案。同样,这是一个独立于方差的问题。