我一直在关注Java类型系统上的paper和Scala是不健全的。为了更好地理解这个问题,我一直试图解决一个较小的相关问题。
我有以下类型:
class Parent
class Child extends Parent
class Grandchild extends Child
class GrandGrandchild extends Grandchild
以下是一些约束抽象类型的特征:
trait LowerBound[T] extends{
type M >: T
}
trait UpperBound[U] extends{
type M <: U
}
我理解这里出现的问题是T
和U
中的UpperBound
和LowerBound
类型无关。因此混合它们可能会有问题。
我可以看到我可以通过提供抽象类型来创建一个对象/ val:
object FamilyMember extends LowerBound[GrandGrandchild] with UpperBound[Parent] {
type M = Child
}
但我未能定义如下特征:
trait FamilyTreeConstraint extends LowerBound[GrandGrandchild] with UpperBound[Parent]
我明白了:
在特征LowerBound中覆盖类型M,边界大于&gt;:A $ A131.this.GrandGrandchild; 在特征UpperBound中键入M,边界&lt ;: A $ A131.this.Parent具有不兼容的类型
现在,如果我没有任何具体类型,参数化FamilyConstraint
将等同于:
trait UpperLower[T,U]{
type M >: T <: U
}
我理解错误。因为T和U是无关的。
但上面的Family Constraint类型不是抽象的,实际上有具体的类型。即我想象编译器最终得到这个:
trait UpperLowerConcrete{
type M >: GrandGrandchild <: Parent
}
我将被允许将M精简为Child
或GrandChild
。但是,它不会变成上面的并且给出与抽象情况相同的错误。
为什么呢?
另外,我是否认为先应用类型优化然后检查类型约束?
答案 0 :(得分:1)
我不知道这种行为的原因,但根据我的经验,如果其约束条件发生变化,通常需要在子类/特征中显式覆盖type
定义。我的意思是,一旦在M
中明确指定FamilyTreeConstraint
的限制,编译器就会满意
trait FamilyTreeConstraint extends LowerBound[GrandGrandchild] with UpperBound[Parent] {
override type M >: Grandchild <: Parent
}