scala隐式转换--案例详解

一、什么是隐式转换?

    隐式转换将某种类型的对象转换成其他类型的对象。隐式转换可以手动指定

    其最核心的就是定义隐式转换函数,即implicit conversion function。定义的隐式转换函数,只要在编写的程序内引入,就会被Scala自动使用。Scala会根据隐式转换函数的签名,在程序中使用到隐式转换函数接收的参数类型定义的对象时,会自动将其传入隐式转换函数,转换为另外一种类型的对象并返回。这就是“隐式转换”。

    隐式转换函数通常不会由用户手动调用,而是由Scala进行调用。因此通常建议将隐式转换函数的名称命名为“one2one”的形式。

    说一下自己的理解,举个例子:比如你去买票的时候,有正常的窗口和特殊人群窗口(学生,军人,残疾人....),你定义了学生的这个类,创建学生的对象,但是没用啊!人家特殊窗口接收的参数只是特殊人群,你怎么证明你是特殊人群呢-----所以你就要拿着你学生证(名字),工作人员对照后发现你属于特殊人群,他就给你开了个证明,你就是特殊人群,这个时候你就可以去买票了

    我们来看这个案例:你会发现在隐式转换中先判断你的类是属于什么( if (obj.getClass == classOf[Student]))-->然后证明( val stu = obj.asInstanceOf[Student)--->最后把你列入特殊人群(new SpecialPerson(stu.name) )。 这就是隐式转换的魅力!

案例:特殊售票窗口(只接受特殊人群,比如学生、老人等)

class SpecialPerson(val name: String)

class Student(val name: String)

class Older(val name: String)

implicit def object2SpecialPerson (obj: Object): SpecialPerson = {

  if (obj.getClass == classOf[Student]) { val stu = obj.asInstanceOf[Student]; new SpecialPerson(stu.name) }

  else if (obj.getClass == classOf[Older]) { val older = obj.asInstanceOf[Older]; new SpecialPerson(older.name) }

  else Nil

}

var ticketNumber = 0

def buySpecialTicket(p: SpecialPerson) = {

  ticketNumber += 1

  "T-" + ticketNumber

}

正常情况下,buySpecialTicket方法接受不了Student和Older类型的对象,如果想这样做,就要用隐式转换,将这两种类型的对象转换成SpecialPerson类型(内部创建SpecialPerson的对象)

二、隐式转换作用域:

Scala默认使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换函数;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换函数。

如果两种都没有还可以手动导入导入:使用import语法引入某个包下的隐式转换函数,比如import test._

三、隐式转换发生时机:

什么时候会进行隐式转换呢,分为三种情况

1、调用某个函数,但是给函数传入的参数的类型,与函数定义的接收参数类型不匹配(案例:特殊售票窗口)

2、使用某个类型的对象,调用某个方法,而这个方法并不存在于该类型时(案例:超人变身)

3、使用某个类型的对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型,与方法定义的接收参数的类型不匹配

加强类的功能:

这一点类似于java中的封装,它可以为某个类定义一个加强版的类,并定义互相之间的隐式转换,从而让源类在使用加强版的方法时,由Scala自动进行隐式转换为加强类,然后再调用该方法。

案例:超人变身

class Man(val name: String)

class Superman(val name: String) {

  def emitLaser = println("emit a laster!")

}

implicit def man2superman(man: Man): Superman = new Superman(man.name)

val leo = new Man("leo")

leo.emitLaser

普通人没有办法用镭射眼( emitLaser方法),但是进行隐式转换后,Man-->Superman,就可以调用了

四、隐式参数

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

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

案例:考试签到

考生到考场签到,所有人共用一支笔signPen,这个时候就可以吧"笔"变量,定义为隐式的

class SignPen {

  def write(content: String) = println(content)

}

implicit val signPen = new SignPen

def signForExam(name: String) (implicit pen: SignPen) {

  pen.write(name + " come to exam in time.")

}

在调用的时候,你只需要---->signForExam("leo")调用,scala就会自动去找隐式的SignPen对象,这样就可以实现调用了

猜你喜欢

转载自blog.csdn.net/S_Running_snail/article/details/85006044