Scala 隐式转换简明教程

前言

对于 Spark 开发者来说 Scala 终究是个绕不过去的坎,
而 对于 Scala ,隐式转换终究也是一个绕不过去的坎。
所以本文就以一种尽可能简单的方式带大家来理解一下 Scala 的隐式转换。

Scala隐式转换 是什么?

  • 隐式转换
    这里我没有找到具体的定义,
    这里我们就用大白话来说一下,
    如果我们想让一台汽车具有挖土机的功能,
    那么我们需要给这个汽车装上一个挖机铲,
    如果装这个挖机铲需要我自己买来装,
    那我们就说是显示转换,
    如果这个挖机铲有人给我自动装上了,
    并且我都不知道到底这个人是谁,是怎么给我装上的,
    那这就是隐式转换。

    ok,这里我们先记住这个小栗子,
    后面我们用代码来实现的时候你就会有更进一步的理解

Scala隐式转换 的使用

  • 隐式参数
    二话不说,我们先上个列子,
    然后再来解释:
 def main(args: Array[String]): Unit = {
      //定义一个隐式参数
      implicit val i_car: String = "*小汽车*"

      def upgradeExcavator(implicit car:String): Unit ={
        println("我将把 "+car+" 升级成 挖机")
      }
      //显示转换
      upgradeExcavator(i_car)
      //隐式转换
      upgradeExcavator
    }
  1. 我们定义了一个隐式参数 i_car.
  2. 接着我们定义了一个方法upgradeExcavator,
    并接受一个参数,打印一句将传入的参数升级为 挖土机
  3. 然后我们显示的传入参数 i_car,调用方法 upgradeExcavator(i_car),
    控制台打印我将把 *小汽车* 升级成挖机
  4. 然后我们直接调用方法 upgradeExcavator,不传入任何参数
    控制台也会打印我将把 *小汽车* 升级成挖机
    很明显,系统自己将我们的 i_car 当做了参数传入。

我们仔细观察就会发现,我们定义 i_car的时候使用了 implicit关键字修饰,
upgradeExcavator的参数一样使用到了 implicit关键字修饰,
当我们调用一个方法,其参数被 implicit关键字修饰 的时候,
如果我们不传入参数,那么该方法就会去其作用域内寻找一个符合该类型的参数,
作为其默认的传入值

ok,这就是隐式参数,那么我们需要注意的是:

  1. 如果作用域内有多个符合规则的参数会怎么样呢?
    报错,因为系统将不知道你要使用的是哪个参数,
    这个时候你就只能使用显示转换了。

  2. 如果我需要传入隐式参数,同时也需要传入显示参数呢?怎么办?
    这种需求我们需要使用 柯里化 函数才行,
    类似这样def upgradeExcavator(car2:String) (implicit car:String)={...}
    这里Scala 高阶函数应用不在讨论之列,
    所以就不多说了。

  3. implicit 关键字必须放在隐式参数定义的开头,
    多个参数只需要在头部标注即可

  • 隐式函数
    同样的,我们先上代码
  class Car() {
    def name() = {
      "普通小汽车"
    }
  }

  class Excavator(car: Car) {
    def name() = {
      car.name() + " 升级成的 挖土机"
    }
    def dig() = {
      println("我具有挖掘功能")
    }
  }

  def main(args: Array[String]): Unit = {
    implicit def upgradeExcavator(car: Car) = {
      new Excavator(car)
    }

    val car = new Car
    println(car.name())
    car.dig()
  }
  1. 我们定义了一个 Car类,其有一个 name方法返回其名字
  2. 我们定义了一个 Excavator类,其有一个 name方法返回其名字,
    和一个挖掘的功能函数dig
  3. 我们创建一个隐式函数,该函数接受一个 Car对象,并返回一个 Excavator
  4. 我们创建一个 Car 实例,打印去名字
  5. 神奇的是,我们竟然可以 car.dig() ,我们的小汽车竟然有挖掘功能

这就是隐式函数,当我们创建了一个对象Car,并调用不属于该对象的方法dig的时候。
那么系统会去作用域内寻找一个隐式函数,
如果他能找到这么一个隐式函数——将 Car转换成 Excavator的函数,
那么你就可以直接把 Car当做Excavator使用

  • 隐式类
    隐式类其实和隐式方法很像,我们将上面的代码改一改,
    很容易就得到以下这个代码:
  class Car() {
    def name() = {
      "普通小汽车"
    }
  }

  implicit class Excavator(car: Car) {
    def name() = {
      car.name() + " 升级成的 挖土机"
    }
    def dig() = {
      println("我具有挖掘功能")
    }
  }

  def main(args: Array[String]): Unit = {
    val car = new Car
    println(car.name())
    car.dig()
  }

我们去掉了隐式方法,将Excavator 修改成了一个隐式类,
那么 当我们创建一个对象 Car,并尝试去调用 dig函数的时候,
系统会去其作用域内寻找是否有这么一个类,其构造函数接受一个 Car,
如果有,那么我们就可以把 car对象直接当Excavator 使用。

OK!到这里 隐式转换的相关使用知识差不多就是这样了,
这里我们多次提到作用域,所以隐式函数什么的,
是可以通过 import 来进行导入的,
这也就是隐式转换可以简化代码的一个重要原因,

本文既然是基于简明二字,所以没有太多的理论,
希望你看完之后会有一点帮助

最后,弱弱的求个赞,可好!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值