Scala抽象类型成员-继承和类型边界
今天,当我试图细化抽象类型成员的类型边界时,在Scala中遇到了一些奇怪的情况 我有两个特性定义类型成员的边界,并将它们组合到一个具体的类中。这很好,但当匹配/铸造特征组合时,只有两个类型边界中的一个是“主动的”,我很难理解为什么 我试着准备一个例子:Scala抽象类型成员-继承和类型边界,scala,abstract-type,type-bounds,type-members,Scala,Abstract Type,Type Bounds,Type Members,今天,当我试图细化抽象类型成员的类型边界时,在Scala中遇到了一些奇怪的情况 我有两个特性定义类型成员的边界,并将它们组合到一个具体的类中。这很好,但当匹配/铸造特征组合时,只有两个类型边界中的一个是“主动的”,我很难理解为什么 我试着准备一个例子: trait L trait R trait Left { type T <: L def get: T } trait Right { type T <: R } 我可以按计划通过get访问我的会员 // works
trait L
trait R
trait Left {
type T <: L
def get: T
}
trait Right {
type T <: R
}
我可以按计划通过get访问我的会员
// works fine
val x1: L with R = concrete.get
但是如果我强制转换为(左加右)或模式匹配,我将无法再访问该成员。根据顺序,我从左或右获得类型边界,但不是两者的组合
// can only access as R, L with R won't work
val x2: R = concrete.asInstanceOf[Left with Right].get
// can only access as L, L with R won' work
val x3: L = concrete.asInstanceOf[Right with Left].get
我知道Left with Right与Right with Left不是一回事,但在这两种情况下,两个类型边界都包含在内,所以为什么我只能使用一个呢
有人能解释一下为什么会发生这种情况吗?第二种类型的成员会覆盖第一种类型的成员
trait L
trait R
trait Left {
type T <: L
def get: T
}
trait Right {
type T <: R
}
object X {
type LR = Left with Right // Right#T overrides Left#T, LR#T is now <: R
type RL = Right with Left // Left#T overrides Right#T, LR#T is now <: L
val concrete = new Left with Right {
override type T = L with R
override def get: T = new L with R {}
}
// ok
val r: R = concrete.asInstanceOf[LR].get
val l: L = concrete.asInstanceOf[RL].get
// ok
implicitly[LR#T <:< R]
implicitly[RL#T <:< L]
// doesn't compile, LR#T is a subclass of R because Right#T overrides Left#T
implicitly[LR#T <:< L]
// doesn't compile, RL#T is a subclass of L because Left#T overrides Right#T
implicitly[RL#T <:< R]
}
trait L
性状R
左特征{
输入T除了TrustNoOne的答案之外,我可以建议以下有一些限制的解决方法。您可以设计自己的类型组合器,而不是使用
来克服类型重写
trait L
trait R
trait Base {
type T
def get: T
}
trait Nil extends Base{
type T = Any
}
trait ~+~[X[_ <: Base] <: Base, Y[_ <: Base] <: Base] extends Base {
type T = Y[X[Nil]]#T
}
trait Left[B <: Base] extends Base {
type T = B#T with L
}
trait Right[B <: Base] extends Base {
type T = B#T with R
}
val concrete = new (Left ~+~ Right) {
def get: T = new L with R {}
}
val x1: L with R = concrete.get
val x2: R = concrete.asInstanceOf[Left ~+~ Right].get
val x3: L = concrete.asInstanceOf[Right ~+~ Left].get
trait L
性状R
性状基础{
T型
def get:T
}
性状零延伸基{
类型T=任何
}
性状~+~[X[;你可以阅读更多关于为什么现在scala覆盖类型以及如何在下一代scala的概念中实现不同的内容我还没来得及深入探讨dotty,但我肯定很期待!你可以在这段视频中看到一些关于未来惊人的东西。关于Shapeled的评论包括Hey,tanks的详细回答Hey,t如果我理解正确的话:问题是左带右
是一个将T绑定到的类型,它不能被实例化(trait-error扩展为左带右
没有编译,因为R!=L)正确的类型是asInstanceOf[Left with Right]{type T=L with R}
也有效(-:
trait L
trait R
trait Base {
type T
def get: T
}
trait Nil extends Base{
type T = Any
}
trait ~+~[X[_ <: Base] <: Base, Y[_ <: Base] <: Base] extends Base {
type T = Y[X[Nil]]#T
}
trait Left[B <: Base] extends Base {
type T = B#T with L
}
trait Right[B <: Base] extends Base {
type T = B#T with R
}
val concrete = new (Left ~+~ Right) {
def get: T = new L with R {}
}
val x1: L with R = concrete.get
val x2: R = concrete.asInstanceOf[Left ~+~ Right].get
val x3: L = concrete.asInstanceOf[Right ~+~ Left].get