Scala Ordered Trait

2018-09-28 18:18 更新

Ordered Trait

比較對象也是胖接口來的比較方便的一個應(yīng)用領(lǐng)域,當(dāng)你需要比較兩個有順序關(guān)系的對象時,如果只需要一個方法就可以知道需要比較的結(jié)果就非常便利。比如,你需要“小于”關(guān)系,你希望使用“< “比較就可以了,如果是“小于等于”,使用”<=”就可以。如果使用瘦接口來定義類,也許你只定義了一個<比較方法,那么如果需要小于等于,你可能需要使用(x<y)|| (x==y)。一個胖接口定義了所有可能的比較運(yùn)算符,使得你可以直接使用<=來書寫代碼。

但胖接口帶來的便利也是有代價的,回頭看看我們前面定義的Rational類;

如果我們需要定義比較操作,則需要定義如下代碼:

class Rational (n:Int, d:Int) {
 ...
  def < (that:Rational) =     this.numer * that.denom  > that.numer * this.denom
  def > (that:Rational) = that < this
  def <=(that:Rational) = (this < that) || (this == that)   def >=(that:Rational) = (this  > that) || (this == that)
}

這個類定義了四個比較運(yùn)算符 < ,>,< =和>=。首先我們注意到后面三個比較運(yùn)算符,都是通過第一個比較運(yùn)算符來實(shí)現(xiàn)的。其次,我們也可以看到,后面三個比較操作對于任意對象都是適用的,和對象的類型無關(guān)。而需要實(shí)現(xiàn)這四個比較運(yùn)算的胖接口都要重復(fù)這些代碼。

Scala 對于比較這種常見的操作,提供了 Ordered Trait 定義,使用它,你可以把所有的比較運(yùn)算的代碼使用一個 compare 定義來替代。這個 ordered trait 可以讓需要實(shí)現(xiàn)比較運(yùn)算的類,通過和 Ordered 特質(zhì)“融合”,而只需實(shí)現(xiàn)一個 compare 方法即可。

因此我們可以修改前面的實(shí)現(xiàn)如下:

class Rational (n:Int, d:Int) extends Ordered[Rational]{
  ...
  override def compare (that:Rational)=
    (this.numer*that.denom)-(that.numer*that.denom)
}

要注意兩點(diǎn),一是 Ordered 需要指明類型參數(shù) Ordered[T] ,類型參數(shù)我們將在后面介紹,這里只需要知道添加所需比較類型的類名稱,本例為 Rational,此外,需要使用 compare 方法。 它比較有序?qū)ο螅?0,表示兩個對象相同,>0表示前面大于后面對象,<0表示前面小于后面對象。

下面為測試結(jié)果:

scala> class Rational (n:Int, d:Int) extends Ordered[Rational]{
     |   require(d!=0)
     |   private val g =gcd (n.abs,d.abs)
     |   val numer =n/g
     |   val denom =d/g
     |   override def toString = numer + "/" +denom
     |   def +(that:Rational)  =
     |     new Rational(
     |       numer * that.denom + that.numer* denom,
     |       denom * that.denom
     |     )
     |   def * (that:Rational) =
     |     new Rational( numer * that.numer, denom * that.denom)
     |   def this(n:Int) = this(n,1)
     |   private def gcd(a:Int,b:Int):Int =
     |     if(b==0) a else gcd(b, a % b)
     |
     |   override def compare (that:Rational)=
     |     (this.numer*that.denom)-(that.numer*that.denom)
     |
     | }
defined class Rational
scala> val half =new Rational(1,2)
half: Rational = 1/2
scala>   val third=new Rational(1,3)
third: Rational = 1/3
scala> half < third res0: Boolean = false
scala> half >= third
res1: Boolean = true

因此,你在需要實(shí)現(xiàn)比較對象時,首先需要考慮 Ordered Trait,看看這個 Trait 能否滿足要求,然后通過和這個 Trait “混合”就可以很方便的實(shí)現(xiàn)對象之間的比較。

此外要注意 Ordered Trait 沒有定義equal 方法,因?yàn)槿绻枰x equal 方法,那么需要檢查傳入?yún)?shù)的類型,Ordered Trait 無法實(shí)現(xiàn),因此你如果需要==比較運(yùn)算符,需要另外定義。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號