1

Let's assume we have a class Pair and some tree of inheritance:

class Pair[ T <: Comparable[T] ](r:T,t:T) {

  def sizeRelationship = r.compareTo(t)
}

sealed class Person(val importance:Int) extends Comparable[Person] {
  override def compareTo(o: Person): Int = ???
}

class Student extends Person(10)
class Teacher extends Person(50)

Now how to modify the upper to be able to create a Pair[Student]?

val mixed: Pair[Person] = new Pair(new Student,new Teacher) /* compiles */
val notMixed = new Pair[Student](new Student, new Student) /* Student does not conform to Comparable */
almendar
  • 1,823
  • 13
  • 23
  • look here for the clues: http://docs.scala-lang.org/tutorials/tour/lower-type-bounds.html – Ashalynd Feb 17 '14 at 23:57
  • 3
    You cannot create _any_ `Pair[Student]` because `Student` violates the type requirements for `Pair`'s `T`. `Student is not <: Comparable[Student]` but only `<: Comparable[Person]`. – 0__ Feb 17 '14 at 23:57

2 Answers2

1

Maybe this helps:

val notMixed = new Pair(new Student, (new Student).asInstanceOf[Person])
Rado Buransky
  • 3,252
  • 18
  • 25
1

A possible solution is the following:

class Pair[ T <% Comparable[T] ](r:T,t:T) {

  def sizeRelationship = r.compareTo(t)
}

Note the viewable-as <% in place of the subtype-of <:

sealed class Person(val importance:Int) {
  def compareTo(o: Person): Int = ???
}

class Student extends Person(10)
class Teacher extends Person(50)

implicit class PersonComparable[T <: Person](x: T) extends Comparable[T] {
  def compareTo(o: T): Int = x.compareTo(o)
}

val mixed: Pair[Person] = new Pair(new Student,new Teacher) /* compiles */
val notMixed = new Pair[Student](new Student, new Student) /* compiles */

The main difference with the original code is that in place of inheriting (implementing) the Comparable trait, the domain classes are retrofitted with it, by means of an implicit class. This makes it possible to exhibit the polymorphic behavior that is required by the type signature of:

val notMixed = new Pair[Student](...)

The main practical advantage versus the solution of using the base type signature in the Pair instance:

val notMixed = new Pair[Person](...)

is more accurate typing of the Pair instances, which in turn can enable more sophisticated processing downstream (e.g. pattern matching, etc).

Community
  • 1
  • 1
Luigi Sgro
  • 639
  • 8
  • 21