scala的隐式转化

来源:互联网 发布:淘宝 跑腿 编辑:程序博客网 时间:2024/06/13 11:03

一、前言

学过java我们都知道,java中的继承是对类的增强,java中的代理、装饰是对对象方法的增强。而在scala中,隐式转换和隐式参数是Scala中两个非常强大的功能,隐式的对类的方法进行增强,丰富现有类库的功能 。利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。

而所谓的隐式转化函数,是指那种以implicit关键字声明的带有单个参数的函数。下面,我会通过几个例子来说明scala的隐式转化。


二、小例子

object MyPredef {  //将File变成RichFile  implicit def fileToRichFile(f: File) = new RichFile(f)
}


import MyPredef._class RichFile(val f: File) {  def read() = Source.fromFile(f).mkString}object RichFile {  def main(args: Array[String]) {    val f = new File("c://words.txt")    //装饰 ,显示的增强    //val contents = new RichFile(f).read()    //隐式转化,会到上下文中去找,是不是有一个隐式的上下文 --->MyPredef._    //File类中没有read方法,但是RichFile中有,所有将File变成了RichFile    val contents = f.read()    println(contents)  }}


三、泛型

[T <: UpperBound]  上界
[T >: LowerBound] 下界
[T <% ViewBound] 视图界定 意味着T可以被隐式转换成M[T]
[T : ContextBound] 上下文界定
[+T] 斜变
[-T] 逆变

[+T] [-T] 一般用于接口中 ,如偏函数中

四、例子

4.1上界

/**  * 指定泛型及上界,传进去的类型(String)必须是Comparable的子类,  * 必须实现Comparable接口,如:Int就不行,因为它没有实现Comparable接口。但我们可以用Integer  * Comparable  *     \____________  *    String\_____  *               \____  */class Pair[T <: Comparable[T]] {  def bigger(first: T, second: T): T = {    if(first.compareTo(second) > 0) first else second  }}object Pair {  def main(args: Array[String]) {    val p = new Pair[String]    println(p.bigger("spark", "hadoop"))  }}


4.2下界

定义类, 然后两个对象进行比较

java实现比较的方法,实现Comparable接口:

class Boy(val name: String, var faceValue: Int) extends Comparable[Boy] {  override def compareTo(o: Boy): Int = {    this.faceValue - o.faceValue  }}

object TestBoy {  def main(args: Array[String]) {    val b1 = new Boy("laoduan", 99)    val b2 = new Boy("laozhao", 999)    val arr = Array[Boy](b1, b2)    //因为我们定义了Boy的比较规则,所以我们可以直接传进去Boy对象就行    val sorted = arr.sortBy(x => x).reverse    for(b <- sorted) {      println(b.name)    }  }}


scala实现比较的方法有两种,实现Ordered(里面有< 、>、<=等)或者Ordering(里面有compare方法、It方法、gt方法)

class Girl(val name: String, var faceValue: Int) {}
object MyPredef {    //另一种new 法:implicit def girl2Ordered(g: Girl) = new Ordered[Girl]{  //  implicit val girl2Ordered = (g: Girl) => new Ordered[Girl] {  //    override def compare(that: Girl): Int = {  //      g.faceValue - that.faceValue  //    }  //  }  trait girl2Ordering extends Ordering[Girl] {    override def compare(x: Girl, y: Girl): Int = {      x.faceValue - y.faceValue    }  }  implicit object Girl extends girl2Ordering}
//视图界定//view bound 他必须传进去一个隐式转换的函数(函数中包括比较类的类型),// 没有对Girl进行侵入,也就是说比较规则没有跟Boy耦合到一起,如java实现comparable接口进耦合了//class Chooser[T <% Ordered[T]] {////  def choose(first: T, second: T) : T = {//    if(first > second) first else second//  }//}//上下文界定//他必须传进去一个隐式转换的值(函数也是值)class Chooser[T : Ordering] {  def choose(first: T, second: T) : T = {    val ord = implicitly[Ordering[T]]//隐式参数,转化成了Ordering,Ordering上有gt方法    if(ord.gt(first, second)) first else second  }}object Chooser {  def main(args: Array[String]) {    import MyPredef._    val c = new Chooser[Girl]    val g1 = new Girl("anglebaby", 90)    val g2 = new Girl("hatano", 99)    val g = c.choose(g1, g2)    println(g.name)  }}

五、例子
class Girl(val name: String, val faceValue: Int, val size: Int) {}


object MyPreDef {//输入是Girl类型,输出时Ordered类型,// implicit def girlToOrdered(girl: Girl) = new Ordered[Girl]{  implicit val girlToOrdered = (girl: Girl) => new Ordered[Girl]{    override def compare(that: Girl): Int = {      if(girl.faceValue == that.faceValue) {        that.size - girl.size      } else {        girl.faceValue - that.faceValue      }    }  }// implicit object girlOrdering extends  [Girl]{  implicit val girlOrdering = new Ordering[Girl] {    override def compare(x: Girl, y: Girl): Int = {      if(x.faceValue == y.faceValue) {        x.size - y.size      } else {        x.faceValue - y.faceValue      }    }  }}


class MissRight[T] {  //相当于ViewBound,利用了柯里化,传的是函数(implicit ord : T => Ordered[T]),可以不传,会到上下文中找类型一样的(输入是T,返回是Ordered[T])  def choose(first: T, second: T)(implicit ord : T => Ordered[T]): T = {    if(first > second) first else second  }  //相当于ContextBound,利用了柯里化,传的是变量(找的是输入【传入参数】是Ordering[T])  def select(first: T, second: T)(implicit ord : Ordering[T]): T ={    if(ord.gt(first, second)) first else second  }//第二个括号是传的是隐式值,但我还想用 >  def random(first: T, second: T)(implicit ord : Ordering[T]): T ={   //把Ordering转化成Ordered    import Ordered.orderingToOrdered    if(first > second) first else second  }}object MissRight {  def main(args: Array[String]) {    val mr = new MissRight[Girl]    val g1 = new Girl("hatanaoYui", 98, 28)    val g2 = new Girl("sora", 98, 33)    //    import MyPreDef._    //val g = mr.choose(g1, g2)    val g = mr.select(g1, g2)    println(g.name)  }}





原创粉丝点击