[Scala隐式转换示例]

一、隐式转换

    Scala编程语言中引入了一种叫做隐式类的新特性。隐式类指的是用implicit关键字修饰的类。在对应的作用域内,带有这个关键字的类的主构造函数可用于隐式转换。隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性。掌握Scala语言隐式转换,了解其隐式转换的作用与原理是很有必要的,否则很难得以应手地处理日常开发中的问题。

在Scala编程语言中,隐式转换到处存在,只不过scala语言为我们隐藏了相应的细节。例如scala中的类继承层次结构中,就存在固有的隐式转换

二、函数的隐式转换

在没有定义隐式转换前,下列赋值的话会报错:

添加隐式转换函数后可以实现Double类型到Int类型的赋值,示例:

  /**
   * 定义了一个从Double类型转换到Int类型的隐式转换方法
   */
  implicit def doubleToInt(value: Double): Int = {
    println("implicitconversion double to int");
    value.toInt
  }

  def main(args: Array[String]): Unit = {
    valx: Int = 9.6
    println(x)
}

输出结果:

implicitconversion double to int

9

 

三、类的隐式转换

   /**
   * 隐式类的运作方式:
   * 隐式类的主构造函数只能有一个参数(有两个以上并不会报错,但是这个隐式类永远不会被编译器作为隐式类在隐式转化中使用)
   * 且这个参数的类型就是将要被转换的目标类型
   * 隐式转换类将包裹目标类型,隐式类的所有方法都会自动"附加"到目标类型上
   *
   * @param origin 隐式类构造函数参数
   */
  implicit class OperateAdd(origin: Int) {
    def add(value: Int): Int = {
      origin + value;
    }
  }
 
  def main(args: Array[String]): Unit = {
    val sum = 5.add(6);
    println(s"5+6=${sum}")
  }

输出结果:

    5+6=11

 

四、隐式转换规则

隐式类有如下几个限制

1、只能在另一个trait//对象的内部定义

2、构造函数只能携带一个非隐式参数

3、在同一作用域内,不能有任何方法、成员或对象与隐式类同名

 

3.1 隐式转换的发生

在什么时候会发生隐式转换呢,主要有一下几种情况。

(1)当方法中的参数类型与实际类型不一致时,会发生隐式转换。

implicit def toInt(value: Int): Int = {
       value.toInt
  }
toInt(9.6)

(2)当调用类中不存在的方法或成员时,会自动将对象进行隐式转换

class Person(varname: String) {}
    class PersonWorker(person: Person) {
       def work = {
           println(s"I am ${person.name},I amprogrammer.")
       }
    }

    def main(args: Array[String]): Unit = {
       //隐式函数将Person隐式转换为PersonWorker类
       implicitdefpersonWorker(person: Person) = new PersonWorker(person)
       //Person类的对象并不存在work方法,此时便会发生隐式转换,将Person类转换成PersonWorker
       val persoon = new Person("小明").work
     }

    输出结果:

    I am 小明,I am programmer.

   

3.2 隐式转换不会发生

在什么时候不会发生隐式转换呢,主要有一下几种情况。

(1)  编译器可以在没有隐式转换时编译通过,则不进行隐式转换

//下面几条语句,不需要自己定义隐式转换编译就可以通过

//因此它不会发生前面定义的隐式转换

 

(2) 如果转换存在二义性,不会发生隐式转换

编译提示隐式转换存在二义性(ambiguous),程序是编译不通过的。

 

(3) 隐式转换不会嵌套进行,嵌套时编译会出错。

五、隐式参数

object ImplicitParameterDemo {
  class PersonInfoFormat(varstartSymbol: String, varendSymbol: String) {}

  class Person(varname: String, varage: Int) {
    //利用柯里化函数的定义方式,将函数的参数利用implicit关键字标识的话,在使用的时候可以不给出implicit对应的参数
    def formatPerson()(implicitformat: PersonInfoFormat) = {
      format.startSymbol+"Name:"+this.name+",age:"+this.age+format.endSymbol
    }
  }

  def main(args: Array[String]): Unit = {
    //程序中定义的变量PersonInfoFormat被称隐式值
    implicit val personFormat = new PersonInfoFormat("[", "]")
    val person: Person = new Person("小明", 22);
    val personInfo = person.formatPerson()
    println(personInfo)
  }
}

输出结果:

[Name:小明,age:22]

 

小结

隐式类与旧的隐式转换的语法(implicitdef)是有细微的不同的,隐式类的运作方式是:隐式类的主构造函数只能有一个参数(有两个以上并不会报错,但是这个隐式类永远不会被编译器作为隐式类在隐式转化中使用),且这个参数的类型就是将要被转换的目标类型。从语义上这很自然:这个隐式转换类将包裹目标类型,隐式类的所有方法都会自动附加到目标类型上。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值