2013-11-06 8 views
8

Ниже приведен код, я пытаюсь запустить:Scala UpperBound и LowerBound концепция

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.printDetails и student.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. Это называется нижней границей.

Пожалуйста, помогите мне, если мое понимание ошибочно и поможет мне понять, почему вышеуказанная проблема наступает. Спасибо, парни.

ответ

13

Ваше понимание не так, но вы не следовали последствиям.

В частности, все параметры имеют, по существу, верхнюю границу Object, если не указана явная верхняя граница. Это происходит в случае метода printStudentDetails в вашем типе MyGenericClassforLowerBound. То есть значение типа Object может быть юридически передано в качестве параметра этого метода. Но тип Object не определяет методы printDetails и printSomeOtherDetails - отсюда ошибка.

Чтобы сделать метод компиляции, вам необходимо будет также обеспечить подходящую верхнюю границу (по аналогии с MyGenericClassforUpperBound), например:

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

Следует отметить, в этом случае, однако, что нижняя эффективно связаны становится излишним, поскольку любой параметр, который подклассы Student может быть успешно передан, поскольку он может быть обработан как тип Student, удовлетворяющий верхней границе - поэтому даже InformationTechnologyStudent и подклассы ComputerScienceStudent могут быть успешно переданы в него. Такая конструкция более полезна, когда вы можете передавать значения, смешивающиеся в типах из двух разных иерархий.

+0

Perfect. Большое спасибо за такое ясное объяснение. Я отмечаю это как ответ. –

+0

Возможно, что любая более правильная терминология Scala, чем Object (которая является типичным для Java)? – Suma

+0

Just FYI, Scala 'AnyRef' отображает на Java' Object'. Тип Scala 'Any' включает коррелирует с примитивными типами Java. См. Http://www.scala-lang.org/api/current/index.html#scala.AnyVal –