scala隐士转换

scala的隐式转化


一、前言

学过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)
  }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值