Подтвердить что ты не робот

Почему параметр типа, связанный с T <: Comparable [T], терпит неудачу при T = Int?

scala> class Foo[T <: Comparable[T]](val x : T)
defined class Foo

scala> (3: Int).asInstanceOf[Comparable[Int]]  
res60: java.lang.Comparable[Int] = 3

scala> new Foo(3)                              
<console>:13: error: inferred type arguments [Int] do not conform to class Foo type parameter bounds [T <: java.lang.Comparable[T]]
       new Foo(3)
       ^

Является ли второе выражение результатом стирания типа?

Как я могу определить Foo, чтобы я мог параметризовать его с помощью Int, но все же быть в состоянии выполнить некоторое поведение порядка с его переменной экземпляра?

4b9b3361

Ответ 1

Используйте привязку .

Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java 1.6.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class Foo[T <% Comparable[T]](val x : T)
defined class Foo

scala> new Foo(3)
res0: Foo[Int] = [email protected]

Ответ 2

Вопрос, как было сказано, остается без ответа (хотя "использование границ представления" решает проблему, что более полезно). Ответ просто в том, что Int в Scala должен быть эквивалентен Int в Java, который вообще не является классом, и поэтому не может быть даже Comparable (хотя это может быть решены в Java 7 с помощью методов защиты... Интересно, сделают ли они это).

Решение, использующее ограничение вида, используется во всем Scala для решения проблемы класса, который может что-то реализовать, но не делает этого, потому что он не находится под управлением Scala - то есть классы Java.

И, конечно же, он может использоваться самими программистами для работы с подобными материалами из библиотек и фреймворков или просто для создания оберток вокруг библиотеки, чтобы дать ему ощущение Scala.

Ответ 3

В качестве альтернативы вы можете использовать привязку :

class Foo[T: Ordering](val v: T)

или

class Foo[T: java.util.Comparator](val v: T)

Контекстная привязка представляет собой утверждение о том, что при вызове конструктора подразумевается неявный Ordering [T] (или java.util.Comparator [T]) и эквивалентен добавлению неявного параметра:

class Foo[T](val v: T)(implicit ev: Ordering[T])

Преимущество этого подхода заключается в том, что он позволит вам использовать альтернативное упорядочение на основе контекста:

// by default, new Foo("a", "c", "b").items == List("a", "b", "c")
class Foo[T: Ordering](xs: T*) {
   val items = xs.toList.sorted
}

// with this object in scope, 
// new Foo("a", "c", "b").items == List("c", "b", "a")
implicit val descending = Ordering[String].reverse