Я полагаю, я не компилирую, потому что вы говорите, что T
должен быть заказан для любого типа.Мы можем написать эквивалентную черту наподобие этой (пожалуйста, поправьте меня, если я ошибаюсь - я не уверен, можно ли ее считать эквивалентной, но по крайней мере вы получите ту же ошибку от компилятора):
trait Example1[A, T <: Ordered[A]] {
val key: T
def before(that: Example1[A, T]): Boolean = (key < that.key)
}
Если вы посмотрите в определение черты Ordered
, вы найдете что-то вроде этого:
trait Ordered[A] extends java.lang.Comparable[A] {
...
def < (that: A): Boolean = (this compare that) < 0
...
}
object Ordered {
/** Lens from Ordering[T] to Ordered[T] */
implicit def orderingToOrdered[T](x: T)(implicit ord: Ordering[T]): Ordered[T] =
new Ordered[T] { def compare(that: T): Int = ord.compare(x, that) }
}
Когда мы будем думать в терминах этого определения - если key
равно Ordered[A]
, чем that.key
должен иметь тип A
(согласно <
сигнатуре метода).Таким образом, компилятор не может использовать его на Ordered[A]
или другими словами T
.И если я не ошибаюсь, он пытается найти Ordering[T]
(в соответствии с неявным определением в объекте-компаньоне), который можно использовать в качестве крайней меры (но он не работает).
Так что, если вы определите параметр типаT
как T <: Ordered[T]
он будет скомпилирован.
В качестве другого решения этой проблемы вы можете использовать контекстную привязку, как в этом примере:
abstract class Example[T: Ordering] {
val key: T
val ord = implicitly[Ordering[T]]
import Ordered._
def before(that: Example[T]): Boolean = key < that.key
}
var one = new Example[Int] {val key = 1}
var two = new Example[Int] {val key = 2}
println(one.before(two)) // prints: true
println(two.before(one)) // prints: false
В этом случае неявное преобразование будет фактическииспользуется потому, что у нас есть доказательства того, что Ordering[T]
существует (черты не могут иметь контекст или границы представления, поэтому я создал абстрактный класс)
Имеет ли это смысл?Если вы обнаружите недостатки в моей логике - пожалуйста, прокомментируйте!(Я буду признателен за это)