Почему привязка параметра типа T <: Comparable [T] не удалась для T = Int? - PullRequest
13 голосов
/ 06 ноября 2010
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's type parameter bounds [T <: java.lang.Comparable[T]]
       new Foo(3)
       ^

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

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

Ответы [ 3 ]

16 голосов
/ 07 ноября 2010

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

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

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

16 голосов
/ 06 ноября 2010

Использовать представление границ .

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] = Foo@9aca82
7 голосов
/ 07 ноября 2010

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

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

или

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

Ограничение контекста представляет собой утверждение о том, что в области видимости существует неявный порядок [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
...