我正在尝试定义一个描述基于其他运算符的运算符的特征。像这样:
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
}
但我得到了这个:值&lt;不是类型参数T
的成员我怎么能说那个和这个类型相同?或者我在尝试一些不可能的事情?
答案 0 :(得分: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
,必须要做两件事。
that
必须使用<
方法接受T
,换句话说,that
必须是LessThanComparable[T]
。我们可以通过说T
必须是LessThanComparable [T]或T <: LessThanComparable[T]
的子类来确保这一点。
this
必须是T
。我们可以使用自我类型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
答案 1 :(得分:0)
更好的方法是遵循标准库中Ordered
和Ordering
特征的结果。前者就像你上面的例子。但事实证明,后者使用“类型类”,更容易,更灵活。
首先,定义一个类型类和一个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]
放入Example
的伴侣对象中。当Example
实例需要它时,它将自动处于隐式范围内。
除此之外:如果你将CompareOps
定义为一个类并使用隐式转换,你实际上不必扩展CompareOps
,但这有点超出了这个答案的范围,所以我'写了here。