一、隱式轉換
首先看一個例子:
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)
}
}
隱式轉換的時機:
-
當方法中的參數的類型與目標類型不一致時。
-
當對象調用類中不存在的方法或成員時,編譯器會自動將對象進行隱式轉換。
-
當對象調用類的方法想被隱式轉換成自己想要轉換的方法。即上面這種情況。
所以上述總結是隱式轉換的時機是在方法被使用之前。
二、比較器
比較器的寫法有很多種,這裏就不討論Comparable和Comparator,只討論Ordered和Ordering
首先討論Ordered:
class Girl(val name:String,val bea:Int){}
-
默認有序,自定義的類繼承Ordered接口,在裏面重寫CompareTo方法,和Comparable相似,
-
通過隱式轉換和示圖界定
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) }
}
- 通過上下文界定
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
}
}
- 不再使用泛型,直接將隱式函數直接利用柯理化的方式定義在方法上面,再使用之前通過隱式轉換變成比較的方法即可。