scala隐式转换

目录

隐式转换的概念

隐式转换的使用

隐式转换做参数类型转换

隐式转换增强现有类型

隐式参数

利用隐式参数进行隐式转换

再议Context Bounds


隐式转换的概念

隐式转换函数(implicit conversion function)是以implicit关键字声明的带有单个参数的函数,这样的函数将被自动应用,将值从一种类型转换为另一种类型。隐式转换函数叫什么名字是无所谓的,因为通常不会由用户手动调用,而是由Scala进行调用。但是如果要使用隐式转换,则需要对隐式转换函数进行导入。因此通常建议将隐式转换函数的名称命名为“one2one”的形式。

scala会考虑如下位置的隐式转换函数:

1、位于源或目标类型的伴生对象中的隐式函数

2、位于当前作用域可以以单个标识符指代的隐式函数

隐式转换在如下三种不同情况下会被考虑:

1、当表达式类型与预期类型不同时

2、当对象访问一个不存在成员时

3、当对象调用某个方法,而这个方法的参数声明与传入参数不匹配时

有三种情况编译器不会尝试使用隐式转换

1、如果代码能够在不使用隐式转换的前提下通过编译,则不会使用隐式转换

2、编译器不会尝试同事执行多个转换

3、存在二义性的转换是错误。

隐式转换的使用

隐式转换做参数类型转换

  // 案例:特殊售票窗口(只接受特殊人群,比如学生、老人等)
  class SpecialPerson(val name : String)
  class Student(val name : String)
  class Older(val name : String)
  
  //隐式转换函数,将Student和Older转变成SpecialPerson类型
  implicit def object2SpecialPerson(obj : Object) : SpecialPerson = {
    obj match{
      case a : Student => {val stu = obj.asInstanceOf[Student];new SpecialPerson(stu.name)}
      case b : Older =>{val old = obj.asInstanceOf[Older];new SpecialPerson(old.name)}
      case _ => Nil
    }
  }
  
  def buySpecialTicket(sp : SpecialPerson){
    println("buySpecialTicket success " + sp.name)
  }
  buySpecialTicket(new Student("Student"))

运行结果:

隐式转换增强现有类型

  class Man(val name : String)
  class Super(val name : String){
    println(name + ", superman")
    def supperman(){
      println("superman")
    }
  }
  implicit def man2Super(man : Man) = new Super(man.name)
  val man = new Man("liumingxin")
  println("---------")
  man.supperman
  man.supperman

运行结果:

由此可见,当调用到隐式转换之后类型的方法时,会先调用隐士转换方法,再调用,而且每一次调用都会先调用隐士转换方法,在隐士转换方法中创建出新的对象,那么每一次的调用都要创建新的对象。

隐式参数

所谓的隐式参数,指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的对象,即隐式值,并注入参数。

Scala会在两个范围内查找:一种是当前作用域内可见的val或var定义的隐式变量;一种是隐式参数类型的伴生对象内的隐式值。

  case class Delimiters(left : String, right : String)
  def quote(content : String)(implicit d : Delimiters){
    println(d.left + content + d.right )
  }
  implicit val defaultDelimiters = Delimiters("<",">")
  quote("haha")

运行结果:

利用隐式参数进行隐式转换

首先我们先看一个例子:

这里因为a没有明确的类型,编译器不确定它有<方法,因此报错。

为了满足上面的需求,我们使用隐式参数,转换一下,让a拥有<方法

Ordered[T]特质中有一个接受T参数的<操作符,因此不会出现最初的错误。

结合隐式转换的概念,隐式转换就是以implicit关键字声明的带有单个参数的函数,“implicit order : T => Ordered[T]”完全符合概念,因此上面的写法也满足隐式转换,将T隐式转换成了Ordered[T]对象。它不仅是隐式参数,也是隐式转换,因此也可以这样写:

再议Context Bounds

scala中的模式匹配和样例类 中已经有讲过Context Boundse了。Context Bounds是一种特殊的Bounds,它会根据泛型类型的声明,比如“T: 类型”要求必须存在一个类型为“类型[T]”的隐式值。表现形式为“T : M”,其中M是一个泛型类型,它要求作用于中存在一个类型为M[T]的隐式值。

scala的学习与研究将告一段落,接下来要开始探索Spark源码了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值