Scala UpperBound和LowerBound概念

时间:2013-11-06 20:11:20

标签: scala generics variance subtyping

以下是我正在尝试运行的代码:

class Student {
  def printDetails = println("I am a student")
  def printSomeOtherDetails = println("I love Studying")
}

class ComputerScienceStudent extends Student {
  override def printDetails = println("I am a Computer Science Student")
  override def printSomeOtherDetails = println("I love Scala")
}

class InformationTechnologyStudent extends Student {
  override def printDetails = println("I am an Information Technology Student")
  override def printSomeOtherDetails = println("I love Java")
}

class MyGenericClassForUpperBound {
  def printStudentDetails[S <: Student](student: S) = {
    student.printDetails
    student.printSomeOtherDetails
  }
}

class MyGenericClassforLowerBound {
  def printStudentDetails[S >: ComputerScienceStudent](student: S) = {
    student.printDetails
    student.printSomeOtherDetails
  }
}

来自printStudentDetails的方法MyGenericClassforLowerBound正在创建问题。陈述student.printDetailsstudent.printSomeOtherDetails告诉我

value printDetails is not a member of type parameter S

据我所知:

  • Q[A <: B]表示类/方法Q可以接受类A的任何对象,其中类A是类B的子类型。这称为上限。
  • Q[A >: B]表示类/方法Q可以接受类A的任何对象,其中类A是类B的超类型。这称为下界。

如果我的理解是错误的,请帮助我,并帮助我理解为什么上述问题即将来临。谢谢你们。

1 个答案:

答案 0 :(得分:14)

你的理解没有错,但你没有遵循后果。

具体而言,如果没有提供明确的上限,则所有参数实际上都具有Object的上限。对于类型printStudentDetails中的方法MyGenericClassforLowerBound,会发生这种情况。也就是说,类型Object的值可以合法地作为参数传递给此方法。但是类型Object未定义方法printDetailsprintSomeOtherDetails - 因此错误。

要使方法编译,您还需要提供合适的上限(类似于MyGenericClassforUpperBound),例如:

def printStudentDetails[S >: ComputerScienceStudent <: Student](student: S) = { ...

但是,在这种情况下应该注意,下限实际上变得多余,因为子类Student的任何参数都可以成功传递,因为它可以被视为类型Student,满足上限 - 所以偶数InformationTechnologyStudentComputerScienceStudent的子类可以成功传递给它。当您可以传递来自两个不同层次结构的类型的值时,这种结构更有用。