2

我正在尝试定义一个特征来描述基于其他运算符的运算符。像这样的东西:

trait LessThanComparable[T] {
    def < (that: T) : Boolean

    def > (that: T) = that < this
}

然后我使用它:

class Example(val x : Int) extends LessThanComparable[Example] {
    def < (that: Example) = x < that.x
}

但我明白了:值 < 不是类型参数 T 的成员

我怎么能说那和这属于同一类型?还是我在尝试一些不可能的事情?

4

2 回答 2

2

我认为这就是你想要的:

trait LessThanComparable[T <: LessThanComparable[T]] { this: T =>
  def <(that: T): Boolean

  def >(that: T) = that < this
}

class Example(val x: Int) extends LessThanComparable[Example] {
  def <(that: Example) = x < that.x
}

为了能够说that < this,有两件事必须成立。

  1. that必须有一个<接受 a 的方法T,或者换句话说,that必须是 a LessThanComparable[T]。我们可以通过说 thatT必须是 LessThanComparable[T] 或 的子类来确保这一点T <: LessThanComparable[T]

  2. this必须是一个T。我们可以通过使用 self 类型来确保这一点this: T =>

那么,

val a = new Example(5)
val b = new Example(4)

println(a < b)  // false
println(a > b)  // true
println(b < a)  // true
println(b > a)  // false
于 2012-09-22T01:15:51.603 回答
0

更好的方法是遵循标准库中的OrderedOrdering特征。前者类似于您上面的示例。但事实证明,后者使用“类型类”更容易、更灵活。

首先,定义一个类型类和一个 mixin 特征:

class Ord[T](val lessThan: (T, T) => Boolean)

trait CompareOps[T] { this: T =>
  def < (that: T)(implicit ord: Ord[T]) = ord.lessThan(this, that)
  def > (that: T)(implicit ord: Ord[T]) = ord.lessThan(that, this)
}

现在,对于您的示例,您所要做的就是将类型类的实例放入隐式范围:

case class Example(x: Int) extends CompareOps[Example]

implicit val exampleOrd = new Ord[Example](_.x < _.x)

scala> Example(3) > Example(4)
res0: Boolean = false

scala> Example(3) < Example(4)
res1: Boolean = true

通常,当您编写一个类时,您会放入Ord[Example]intoExample的伴随对象。Example然后,当实例需要它时,它将自动处于隐式范围内。

CompareOps另外:如果你定义为一个类并使用隐式转换,你实际上不必扩展CompareOps,但这有点超出了这个答案的范围,所以我在 这里写了。

于 2012-09-22T04:03:35.457 回答