引言

Scala提供的隐式转换和隐式参数功能,是非常有特色的功能。是Java等编程语言所没有的功能。它可以允许你手动指定,将某种类型的对象转换成其他类型的对象。通过这些功能可以实现非常强大而且特殊的功能。

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

隐式转换函数叫什么名字是无所谓的,因为通常不会由用户手动调用,而是由Scala进行调用。但是如果要使用隐式转换,则需要对隐式转换函数进行导入。因此通常建议将隐式转换函数的名称命名为“one2one”的形式。

隐式转换

要实现隐式转换,只要程序可见的范围内定义隐式转换函数即可。Scala会自动调用隐式转换函数。

隐式转换函数与普通函数唯一的区别就是要以implicit开头,而且最好要定义函数返回类型。

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

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
}
// 测试
scala> val stu = new Student("sparks")
stu: Student = Student@388623ad
scala> val old = new Older("leo")
old: Older = Older@3453acd2
// 学生和老人通过隐式转换后均可买特殊票
scala> buySpecialTicket(stu)
res9: String = T-1
scala> buySpecialTicket(old)
res10: String = T-2

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

隐式转换非常强大的一个功能,就是可以在不知不觉中加强现有类型的功能。也就是说,可以为某个类定义一个加强版的类,并定义互相之间的隐式转换函数,从而让源类在使用加强版类的方法时,由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)
defined class Man
defined class Superman
man2superman: (man: Man)Superman
// 创建普通人类对象sparks
scala> val sparks = new Man("leo")
sparks: Man = Man@75c56eb9
// sparks通过隐式转换变身超人,拥有发射激光方法
scala> sparks.emitLaser
emit a laster!

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

Scala默认会使用两种隐式转换,一种是源类型或目标类型的伴生对象内的的隐式转化函数;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换函数。(上面两个例子都属于第二种情况)

如果隐式转换函数不在上述两种情况下的话,那么就必须手动使用import语法导入,例如:import test._ 。通常建议,仅仅在需要进行隐式转换的地方,比如某个函数或者方法内,用import导入隐式转换函数,这样可以缩小隐式转换函数的作用域,避免不需要的隐式转换。

隐式转换触发条件

  1. 调用某个函数,但是给函数传入的参数类型与函数定义的接收类型不匹配。(案例:特殊售票窗口) 
  2. 使用某个类型的对象,调用某个方法,而这个方法并不存在于该类型时。(案例:超人变身) 
  3. 使用某个类型的对象,调用该类中的某个方法,虽然该类型有这个方法,但是给方法传入的参数类型与定义接收类型不匹配(案例:特殊售票窗口加强版)

  
案例:特殊售票窗口加强版

// 定义售票窗口类
class TicketHouse {
var ticketNumber = 0
def buySpecialTicket(p: SpecialPerson) = {
ticketNumber += 1
"T-" + ticketNumber
}
}
defined class TicketHouse
// 测试
scala> val ticketHouse = new TicketHouse
ticketHouse: TicketHouse = TicketHouse@522b2631
scala> val spark = new Student("sparks")
spark: Student = Student@588ffeb
// 当传入一个学生对象时,触发第三种隐式转换条件
scala> ticketHouse.buySpecialTicket(spark)
res2: String = T-1

隐式参数

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

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

案例:考试签到

class SignPen{
def write(content: String) =println(content)
}
// 定义隐式参数
implicit val signPen = new SignPen
// 函数中使用隐式参数,此时scala会尝试找到一个指定SignPen类型的用implicit修饰的对象
def signForExam(name: String) (implicit signPen: SignPen) {
signPen.write(name + " come to exam in time.")
}
defined class SignPen
signPen: SignPen = SignPen@773dab28
signForExam: (name: String)(implicit signPen: SignPen)Unit
// 测试:当同学sparks来签到时,函数调用隐式参数的值完成签到
scala> signForExam("sparks")
sparks come to exam in time.

Java数组与Scala数组的隐式转换

我们知道在Scala代码中,是直接可以调用JDK(JAVA)API的,比如调用一个Java数组类的方法,势必可能会传入Java类型的ArrayList,但是Scala中构造出来的其实是ArrayBuffer,你直接把Scala的ArrayBuffer传入Java接收ArrayList的方法,肯定不行。所以这时候隐式转换就派上用场了!

// 导入隐式转换函数,将scala的buffer类型转换为javalist类型
import scala.collection.JavaConversions.bufferAsJavaList
import scala.collection.mutable.ArrayBuffer
// 测试
val command = ArrayBuffer("javac", "C:\\Users\\Administrator\\Desktop\\Hello.java")
val processBuilder = new ProcessBuilder(command)
val process = processBuilder.start()
// 转换成功
val res = process.waitFor()
res: Int = 2
// 导入隐式转换函数,将javalist类型转换为scala的buffer类型
import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.mutable.Buffer
// 转换成功
scala> val cmd: Buffer[String] = processBuilder.command()
cmd: scala.collection.mutable.Buffer[String] = ArrayBuffer(javac, C:\Users\Administrator\Desktop\Hel
lo.java)

Java Map与Scala Map的隐式转换

// Java Map转换为Scala Map
import scala.collection.JavaConversions.mapAsScalaMap
// 创建Java.util.HashMap对象
val javaScores = new java.util.HashMap[String, Int]()
javaScores.put("Alice", 10)
javaScores.put("Bob", 3)
javaScores.put("Cindy", 8)
// 转换成功
val scalaScorces: scala.collection.mutable.Map[String, Int] = javaScores
scalaScorces: scala.collection.mutable.Map[String,Int] = Map(Bob -> 3, Alice -> 10, Cindy -> 8)
// Scala Map转换为Java Map
import scala.collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._
scala> val scalaAttrMap = Map(FAMILY -> "Sermi", SIZE -> 12)
scalaAttrMap: scala.collection.immutable.Map[java.awt.font.TextAttribute,Any] = Map(java.awt.font.Te
xtAttribute(family) -> Sermi, java.awt.font.TextAttribute(size) -> 12)
// 转换成功
scala> val font = new java.awt.Font(scalaAttrMap)
font: java.awt.Font = java.awt.Font[family=Dialog,name=Sermi,style=plain,size=12]

转载于:https://www.cnblogs.com/LiCheng-/p/8076090.html

Scala入门系列(十二):隐式转换相关推荐

  1. Scala入门到精通——第十八节 隐式转换与隐式参数(一)

    本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...

  2. Reflex WMS入门系列十二:Reflex里的Location

    Reflex WMS入门系列十二:Reflex里的Location 玩过SAP系统里的人都知道,在SAP系统里库存管理分为IM Level和WM Level.IM Level的仓库,在SAP里被定义为 ...

  3. 【ASE入门学习】ASE入门系列十二——Ramp采样(渐变采样)

    涵盖知识:边缘光.软粒子.渐变采样 RampY是控制渐变分层的(即渐变图可能包含多种形式的渐变色)根据渐变因子是X还是Y来确定分量控制,上例子是以边缘光颜色作为采样渐变色的X值,Y固定为0. 其中Di ...

  4. scala基础之隐式转换

    一 隐式转换 隐式转换函数,也被称作隐式视图,它是可以把一种类型转换成另外一种类型,进而可以使用另外一种类型的属性和方法,从而满足表达式的要求 语法格式:implicit def 函数名(参数名:参数 ...

  5. Scala入门到精通——第十九节 隐式转换与隐式参数(二)

    本节主要内容 隐式参数中的隐式转换 函数中隐式参数使用概要 隐式转换问题梳理 1. 隐式参数中的隐式转换 前一讲中,我们提到函数中如果存在隐式参数,在使用该函数的时候如果不给定对应的参数,则编译器会自 ...

  6. 2021年大数据常用语言Scala(三十八):scala高级用法 隐式转换和隐式参数

    目录 隐式转换和隐式参数 隐式转换 自动导入隐式转换方法 隐式转换的时机 隐式参数 隐式转换和隐式参数 隐式转换和隐式参数是scala非常有特色的功能,也是Java等其他编程语言没有的功能.我们可以很 ...

  7. scala入门-10 隐式转换、隐式参数、隐式类

    到目前为止,隐式转换是scala的重点和难点了,加油~ 我们先创建一个类名称叫Implicit.scala 再看一个隐式参数的例子: 上面的例子中使用了隐式参数,我们也可以明显的指明参数: 下面看一下 ...

  8. 7.scala初识 柯里化、隐式参数、隐式转换、视图边界、上界、下界、协变、逆变

    1.前言: 学过java我们都知道,java中的继承是对类的增强,java中的代理.装饰是对对象方法的增强.而在scala中,隐式转换和隐式参数是Scala中两个非常强大的功能,隐式的对类的方法进行增 ...

  9. scala中的隐式转换、隐式参数和隐式类

    scala中的隐式转换.隐式参数和隐式类 @(SCALA)[scala] scala中的隐式转换隐式参数和隐式类 一隐式转换 1示例 2隐式转换的条件 二隐式参数 1示例 三隐式类 1示例 隐式转换是 ...

  10. Scala 高阶函数(作为值的函数、匿名函数、闭包、柯里化)+隐式转换和隐式参数...

    Scala高级特性 1.    学习目标 1.1.   目标一:深入理解高阶函数 1.2.   目标二:深入理解隐式转换 2.    高阶函数 2.1.   概念 Scala混合了面向对象和函数式的特 ...

最新文章

  1. loadrunner支持https协议的操作方法-经验总结
  2. 使用TCP的简单C/S程序
  3. SUSE Linux启动过程执行脚本顺序
  4. Linux下9个有用的touch命令示例
  5. linux c ecb 加密解密,OpenSSL对数组加密解密的完整实现代码
  6. Android RxJava和改造
  7. Entity Framework 代码先行之约定配置
  8. 对携程处理结果表示满意
  9. 用c语言计算sin计算器,C语言计算器
  10. MATLAB实现SVM多分类(one-vs-rest),利用自带函数fitcsvm
  11. iOS UISwitch控件
  12. 浅谈人机关系在生活中的应用
  13. 微信有哪些隐藏功能?实用隐藏功能合集:建小号、批量群发
  14. Unity机器学习库ml-agents新版本的环境搭建
  15. kaggle经典题--“泰坦尼克号”--0.8275准确率--东北大学20级python大作业开源(附详细解法与全部代码以及实验报告)
  16. 特殊数字符号大全,word 数学符号
  17. 大数据入门之分布式计算框架Spark(2) -- Spark SQL
  18. 开放域对话预训练模型总结
  19. 攒机需要注意的8条技巧 转太平洋网
  20. Very Good!!! - React 入门实例教程

热门文章

  1. Python爬虫入门教程 7-100 蜂鸟网图片爬取之二
  2. 普通高等学校毕业生登记表 计算机水平,普通高等学校全日制毕业生登记表自我鉴定怎么写...
  3. 计算机网络职业评估报告,计算机网络技术专业个人职业生涯规划书.doc
  4. css防爆电机,防爆马达
  5. 汽车驾驶 - 如何调整汽车后视镜
  6. 计算机 管理 被停用,任务管理器已被系统管理员停用,详细教您任务管理器已被系统管理员停用怎么办...
  7. Android关于BottomNavigationView效果实现指南
  8. SaaS模式、技术与案例详解——第17章 案例详解
  9. wex5 导入mysql_Wex5铛铛开发环境搭建步骤
  10. wex5 ajax,关于Ajax请求 - WeX5开发者论坛 - 起步软件技术论坛 - Powered by Discuz!