2012-09-22 84 views
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的成員

我怎麼能說是和這是相同的類型?或者我在嘗試不可能的事情?

回答

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必須有一個<方法,它接受一個T,或者換句話說,that必須是LessThanComparable[T]。我們可以通過說T必須是LessThanComparable [T]或T <: LessThanComparable[T]的子類來保證這一點。

  2. 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 
+0

這正是我想要做的。謝謝:) – Eduardo

0

一個更好的辦法是遵循標準庫中OrderedOrdering特質發揮出來。前者就像你上面的例子。但事實證明,使用「類型類」的後者更容易且更靈活。

首先,定義一個類類和混入特質:現在

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

+0

但我需要一個案例類而不是一個類,對吧? – Eduardo

+0

@Eduardo案例類僅僅是爲了方便實例化。在REPL中像正常的類一樣嘗試。 –

+0

我嘗試使用一個簡單的類,但它沒有工作。 – Eduardo

相關問題