• Spark基础-scala学习(八、隐式转换与隐式参数)


    大纲

    1. 隐式转换
    2. 使用隐式转换加强现有类型
    3. 导入隐式转换函数
    4. 隐式转换的发生时机
    5. 隐式参数

    隐式转换

    1. 要实现隐式转换,只要程序可见的范围内定义隐式转换函数即可。Scala会自动使用隐式转换函数。隐式转换函数与普通函数唯一的语法区别就是,要以implicit开头,而且一定要定义函数返回类型
    2. 案例:特殊售票窗口(只接受特殊人群,比如学生、老人等)
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    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
    }
    
    // Exiting paste mode, now interpreting.
    
    <pastie>:15: warning: implicit conversion method object2SpecialPerson should be enabled
    by making the implicit value scala.language.implicitConversions visible.
    This can be achieved by adding the import clause 'import scala.language.implicitConversions'
    or by setting the compiler option -language:implicitConversions.
    See the Scaladoc for value scala.language.implicitConversions for a discussion
    why the feature should be explicitly enabled.
    implicit def object2SpecialPerson(obj:Object):SpecialPerson = {
                 ^
    defined class SpecialPerson
    defined class Student
    defined class Older
    object2SpecialPerson: (obj: Object)SpecialPerson
    ticketNumber: Int = 0
    buySpecialTicket: (p: SpecialPerson)String
    
    scala> val s = new Student("leo")
    s: Student = Student@4d266391
    
    scala> buySpecialTicket(s)
    res0: String = T-1
    
    scala> val o = new Older("Jike")
    o: Older = Older@6afbe6a1
    
    scala> buySpecialTicket(o)
    res1: String = T-2
    

    使用隐式转换加强现有类型

    1. 隐式转换可以在不知不觉中加强现有类型的功能。也就是说,可以为某个类定义一个加强版的类,并定义互相之间的隐式转换,从而让源类在使用加强版的方法时,由scala自动进行隐式转换为加强类,然后再调用该方法
    2. 案例:超人变身
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    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)
    
    
    // Exiting paste mode, now interpreting.
    
    defined class Man
    defined class Superman
    man2superman: (man: Man)Superman
    
    scala> val leo = new Man("leo")
    leo: Man = Man@618e7761
    
    scala> leo.emitLaser
    emit a laster!
    

    隐式转换函数的作用域与导入

    1. scala会使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换函数;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换函数
    2. 如果隐式转换函数不在上述两种情况下的话,那么就必须手动使用import语法引入某个包下的隐式转换函数,比如import test._ 通常建议,仅仅在需要进行隐式转换的地方,比如某个函数或者方法内,用import导入隐式转换函数,这样可以缩小隐式转换函数的作用域,避免不需要的隐式转换。

    隐式转换的发生时机

    1. 调用某个函数,但是给函数传入的参数的类型,与函数定义的接收参数类型不匹配(案例:特殊售票窗口)
    2. 使用某个类型的对象,调用某个方法,而这个方法并不在于该类型时(案例:超人变身)
    3. 使用某个类型的对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型,与方法定义的接收参数的类型不匹配(案例:特殊售票窗口加强版)
    4. 案例:特殊售票窗口加强版
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    class TicketHouse {
     var ticketNumber= 0
     def buySpecialTicket(p:SpecialPerson) = {
      ticketNumber += 1
      "T-"+ticketNumber
     }
    }
    
    // Exiting paste mode, now interpreting.
    
    defined class TicketHouse
    
    scala> val leo = new Student("leo")
    leo: Student = Student@217dc48e
    
    scala> val ticket = new TicketHouse
    ticket: TicketHouse = TicketHouse@7a5a26b7
    
    scala> ticket.buySpecialTicket(leo)
    res1: String = T-1
    
    

    隐式参数

    1. 所谓的隐式参数,指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的对象,即隐式值,并注入参数
    2. Scala会在两个范围内查找:一种是当前作用域内可见的val或var定义的隐式变量;一种是隐式参数类型的伴生对象内的隐式值
    3. 案例:考试签到
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    class SignPen{
     def write(content:String) = println(content)
    }
    implicit val signPen = new SignPen
    
    def signForExam(name:String)(implicit signPen:SignPen){
     signPen.write(name+" come to exam in time.")
    }
    
    // Exiting paste mode, now interpreting.
    
    defined class SignPen
    signPen: SignPen = SignPen@6c4d0224
    signForExam: (name: String)(implicit signPen: SignPen)Unit
    
    scala> signForExam("leo")(signPen)
    leo come to exam in time.
    
    
  • 相关阅读:
    ARM开发工具软件命令具体解释---嵌入式回归第三篇
    Java模拟公司置办货物系统(二)
    springmvc mybatis 声明式事务管理回滚失效,(checked回滚)捕捉异常,传输错误信息
    Django Drops
    从 &quot;org.apache.hadoop.security.AccessControlException:Permission denied: user=...&quot; 看Hadoop 的用户登陆认证
    iOS中Storyboard使用要点记录
    ACdream 1084 寒假安排(阶乘素因子分解)
    【死磕Java并发】-----J.U.C之AQS:CLH同步队列
    使用freemarker做邮件发送模板
    springboot 使用freemarker自定义标签
  • 原文地址:https://www.cnblogs.com/sky-chen/p/10134198.html
Copyright © 2020-2023  润新知