繁体   English   中英

Scala类型界限行为(方法与类)

[英]Scala type bounds behaviour (method vs class)

对于Scala专家来说,这可能是一件容易的事。 我正在阅读类型绑定约束,并想知道是否遗漏了一些东西,因为我看到了一些意想不到的行为。 假设我们在这样的层次结构中有三种类型A,B,C,我们正在针对它们进行类型界限的实验:

class A {
}

class B extends A {
}

class C extends B {
}

class MyList1 { // T super B
  def add[T >: B](a: T): Unit = {}
}

class MyList2 { // T extends B
  def add[T <: B](a: T): Unit = {}
}

class MyList3[T >: B] { // T super B
  def add(a: T): Unit = {}
}

class MyList4[T <: B] { // T extends B
  def add(a: T): Unit = {}
}

object BoundsClass {

  def main(args: Array[String]) {
    val l1 = new MyList1
    l1.add(new A) 
    l1.add(new B)
    l1.add(new C) // why is this allowed??

    val l2 = new MyList2
    // l2.add(new A) // not allowed (OK)
    l2.add(new B)
    l2.add(new C)

    val l3a = new MyList3[A]
    val l3b = new MyList3[B]
    // val l3c = new MyList3[C] // not allowed (OK)

    // val l4a = new MyList4[A] // not allowed (OK)
    val l4b = new MyList4[B]
    val l4c = new MyList4[C]
  }

}

除一种情况外,其他所有集合的行为均符合预期,请参见l1.add(new C);。 不会导致编译错误。 为什么允许这样做?

谢谢!

我并没有声称自己是斯卡拉大律师,但我会为此而a之以鼻。

您已经按照A >: B >: C定义了类型层次结构,因此您可以执行以下操作

val aa: A = new A
val ab: A = new B
val ac: A = new C

val bb: B = new B
val bc: B = new C

val cc: C = new C

就像您可以说val a: Any = new Whatever

因此,当您尝试向l1添加new C时,它会被视为B实例,因为这是它自身最接近该方法的类型范围的可用版本。

当以这种方式使用时,下界没有用。 您不能将value参数强制设置为下限,因为根据Liskov替换原则 ,您必须能够在需要类实例的任何地方使用子类实例。 因此,您的代码可以编译,因为new C可以视为B的实例。

通常,由于这个原因,在方法的值参数上设置下限是没有用的。 在您绑定类的类型参数的第二种情况下,下界无疑更有用。 所有类型参数都是按编译类型解析的,因此,您可以期望编译器在第二种情况下产生编译器错误。 您可以在此处找到下限用法的更具体示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM