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