對Scala語言中隱式轉換和比較器的見解

一、隱式轉換

首先看一個例子:

import java.io.File
import scala.io.Source
object Context{
  implicit def fileToRichFile(file:File) = new RichFile(file)
}
class RichFile(file:File){
    def read():String = Source.fromFile(file).mkString
}

object implicitValue {
  def main(args: Array[String]): Unit = {
    val file = new File("C:/words.log")
    import Context.fileToRichFile
    val value = file.read()
    println(value)
  }
}
隱式轉換的時機:
  1. 當方法中的參數的類型與目標類型不一致時。

  2. 當對象調用類中不存在的方法或成員時,編譯器會自動將對象進行隱式轉換。

  3. 當對象調用類的方法想被隱式轉換成自己想要轉換的方法。即上面這種情況。

所以上述總結是隱式轉換的時機是在方法被使用之前。

二、比較器

比較器的寫法有很多種,這裏就不討論Comparable和Comparator,只討論Ordered和Ordering

首先討論Ordered:

class Girl(val name:String,val bea:Int){}
  1. 默認有序,自定義的類繼承Ordered接口,在裏面重寫CompareTo方法,和Comparable相似,

  2. 通過隱式轉換和示圖界定

   object Context {
       implicit def chooseGirl = (g:Girl) => new Ordered[Girl]{
       override def compare(that: Girl): Int = {
         g.name.compareTo(that.name)
       }
   }
   
   class Chooser[T <% Ordered[T]]{
        def choose(g1:T, g2:T):T = {
          if(g1>g2) g1 else g2
        }
   }
   
   object Chooser {
       def main(args: Array[String]): Unit = {
         import Context._
         //Girl<%表明 Girl類的上屆是Ordered,即泛型的類型必須是"某種類型"或某種類型的"子類"
         val c = new Chooser[Girl]
         val g1 = new Girl( "張三", 100 )
         val g2 = new Girl( "李四", 99 )
         val g = c.choose( g1, g2 )
   }
  • 把隱式轉換寫到類的前面的原因是,再加載類的時候加載方法,需要把方法進行隱式轉換,而不是調用方法時候在進行轉換。否則加載不到Ordered[Girl]方法而無法進行比較。

    Ordered的隱式轉換

 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) }
 }
  1. 通過上下文界定
  object Context {
      implicit def chooseGirl= new Ordering[Girl]{
       override def compare(x: Girl, y: Girl): Int = {
         x.bea - y.bea
       }
          
       /**
       另一種寫法:
     trait chooseGirl extends Ordering[Girl] {
      override def compare(x: Girl, y: Girl): Int = {
        x.bea - y.bea
      }
    }
    implicit object Girl extends chooseGirl
       */
    }
      //上下文界定
      class Chooser[T: Ordering] {
        def choose(g1: T, g2: T)= {
          val ord = implicitly[Ordering[T]]
          if (ord.gt( g1, g2 )) g1 else g2
        }
      }
      
      object Chooser {
        def main(args: Array[String]): Unit = {
          import Context._
          //"T:Ordering" :表示將T變成Ordering[T]
          val c = new Chooser[Girl]
          val g1 = new Girl( "張三", 100 )
          val g2 = new Girl( "李四", 99 )
          val g = c.choose( g1, g2 )
          println( g.name )
        }
      }
 def apply[T](implicit ord: Ordering[T]) = ord

三、比較器直接使用隱式轉換

class Chooser[T]{
  def choose1(g1:T,g2:T)(implicit ord: T => Ordered[T]):T={
      if(g1>g2) g1 else g2
   }

  def choose2(g1:T,g2:T)(implicit ord: Ordering[T]):T={
    if(ord.gt(g1,g2)) g1 else g2
  }
 }
  1. 不再使用泛型,直接將隱式函數直接利用柯理化的方式定義在方法上面,再使用之前通過隱式轉換變成比較的方法即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章