scala学习手记35 - 隐式类型转换
先来看一下下面的内容:
2 days “ago”
5 days “from_now”
如上的内容具体应该是什么呢?不过怎么看也不像是代码。不过既然是在学代码,拿不是代码的东西出来做什么!
非要强说是代码的话,那么执行起来肯定是要报错的——因为scala的Int和RichInt,以及Integer中都没有days这样的方法:

如果说不是代码的话,那么scala中的to或until本来看起来也不像代码:
2 to 6
2 until 7
现在剩下的就是怎么为整型值添加上days方法。这就涉及到如何扩展整型类了。我自己想了好久也没想到妥帖的法子。
教材中提供了一个方案,就是采用隐式类型转换。
隐式类型转换可以帮助我们扩展语言,创建“专用于特定应用和领域”的词汇或语法,也可以帮助我们创建属于自己的领域专用语言。
关于隐式类型转换,教材上就是这么说的。从这句话里可以看到隐式类型转换为我们留下了巨大的扩展空间。
先来看看如何解决眼前的事情。要为整型值添加RichInt方法需要先创建一个DateHelper类:
class DateHelper(number: Int) {
def days(when: String): Date = {
val date = Calendar.getInstance()
when match {
case "ago" => date.add(Calendar.DAY_OF_MONTH, -number)
case "from_now" => date.add(Calendar.DAY_OF_MONTH, number)
case _ => date
}
date.getTime()
}
}
在DateHelper类中提供了我们需要的days方法。我们要做的就是将给定的数字转换为DateHelper对象。类继承是不行的,强制类型转换也是不行的,可以考虑在需要的时候将整型值转换为DateHelper实例。简单的把方法标记为implicit,只要这个方法在当前范围内存在,scala就会自动调用这个方法:
implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)
把上面的代码同DateHelper类一起运行就可以自动将整数值转换为DateHelper实例,然后就可以调用days()方法了。
来看一下完整的代码:
import java.util._
class DateHelper(number: Int) {
def days(when: String): Date = {
val date = Calendar.getInstance()
when match {
case "ago" => date.add(Calendar.DAY_OF_MONTH, -number)
case "from_now" => date.add(Calendar.DAY_OF_MONTH, number)
case _ => date
}
date.getTime()
}
}
implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)
val ago = "ago"
val from_now = "from_now"
val past = 2 days ago
val appointment = 5 days from_now
println(past)
println(appointment)
看一下执行结果:

接下来可以对代码稍作调整。我们并不想在每次需要转换时都去写隐式转换器。把这个转换器放到一个单独的单例对象里,可以获得更好的重用性,也更加易用。可以把转换器挪到DateHelper的伴生对象里:
import java.util._
class DateHelper(number: Int) {
def days(when: String): Date = {
val date = Calendar.getInstance()
when match {
case DateHelper.ago => date.add(Calendar.DAY_OF_MONTH, -number)
case DateHelper.from_now => date.add(Calendar.DAY_OF_MONTH, number)
case _ => date
} date.getTime()
}
}
object DateHelper {
val ago = "ago"
val from_now = "from_now"
implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)
}
导入DateHelper时,Scala会自动的找到转换器。这是因为Scala会在当前范围和导入的范围内进行转换。
在Predef对象里,Scala已经定义了一些隐式转换,Scala会默认导入它们。这样的话,比如说,当我们写1 to 3时,Scala就会隐式的将1从Int转换为其富封装器RichInt,然后,调用to()方法。Scala一次至多应用一个隐式转换。
在当前范围内,如果发现通过类型转换有助于操作、方法调用或类型转换的成功完成,就会进行转换。
######################
scala学习手记35 - 隐式类型转换的更多相关文章
- Scala学习二十一——隐式转换和隐式参数
一.本章要点 隐式转换用于类型之间的转换 必须引入隐式转换,并确保它们可以以单个标识符的形式出现在当前作用域 隐式参数列表会要求指定类型的对象.它们可以从当前作用域中以单个标识符定义的隐式对象的获取, ...
- Scala 学习笔记之隐式参数和隐式转换并用
隐式转换条件: 1. 当表达式类型与预期的类型不同时 2.当对象访问一个不存在的成员时 3.当对象调用某个方法,而该方法的参数声明与传入参数不相匹时. 隐式转换搜索范围: 1. 位于源火目标类型伴生对 ...
- JavaScript学习总结(二、隐式类型转换、eval())
一.(避免)隐式类型转换 console.log(false == 0); //logs true; console.log(false === 0); //logs false; conso ...
- Scala进阶之路-Scala高级语法之隐式(implicit)详解
Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...
- C++的隐式类型转换
C++是一种复杂的语言,其中有许多“好玩”的特性,学习C++的过程就像在海边捡一颗颗石头,只要坚持不懈,也许一颗颗小石头也能建起你自己小小的城堡. 废话完后,讲讲自己捡到的石头:隐式类型转换 学习出处 ...
- 深入js隐式类型转换
前言 相信刚开始了解js的时候,都会遇到 2 =='2',但是 1+'2' == '1'+'2'为false的情况,这时候应该会是一脸懵逼的状态,不得不感慨js弱类型的灵活让人发指,隐式类型转换就是这 ...
- javascript的隐式类型转换
首先简单了解js的typeof,会返回六种类型 即 number string boolen function object undefined 也就是六种基本数据类型 显示类型转换大概有以下几种: ...
- js条件判断时隐式类型转换
Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...
- dynamic_cast 和 static_cast 隐式类型转换的区别
首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...
随机推荐
- 160722、Javascript函数节流
最近在做网页的时候有个需求,就是浏览器窗口改变的时候需要改一些页面元素大小,于是乎很自然的想到了window的resize事件,于是乎我是这么写的 <!DOCTYPE html> < ...
- apk获取源码(dex2jar、jd-gui)
1.下载dex2jar.zip,并解压文件 2.下载jd-gui.zip,解压文件 3.解压apk文件,找到其中的classes.dex 4.将classes.dex复制到dex2jar.bat所在目 ...
- Pycharm创建Django admin用户名和密码
1.Tools>Run manage.py Task 2.依次输入: makemigrations migrate createsuperuser 如: manage.py@production ...
- 巨蟒python全栈开发-第8天 文件操作
一.文件操作 今日大纲: 1.文件操作->open() open 打开 f=open(文件路径,mode='模式',encoding='编码格式') #python最最底层操作的就是bytes ...
- 小团队交流为什么 :wq! :wq 二者结果一致?
w 答案: :q 执行失败--->提示-已经修改,但是尚未保存,+!强制不保存退出 :w 保存
- 转!!Java的三种代理模式
转自 http://www.cnblogs.com/cenyu/p/6289209.html 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象 ...
- Django-admin列表展示上传图片
1.在models.py文件中创建表ImageField类型字段 class user(models.Model): img = models.ImageField(upload_to='static ...
- 我的Android进阶之旅------>解决Android Studio编译后安装apk报错:The APK file does not exist on disk
1.错误描述 今天用Android Studio编译应用后安装APK的时候,报错了,错误如下所示: The APK file build\outputs\apk\OYP_2.3.4_I2Base_64 ...
- 003-mysql查询表的数据大小
在需要备份数据库里面的数据时,我们需要知道数据库占用了多少磁盘大小,可以通过一些sql语句查询到整个数据库的容量,也可以单独查看表所占容量. 1.查看数据库表结构大小,要查询表所占的容量,就是把表的数 ...
- selenium破解数字验证码
搞了半天,总算弄出来了,识别率还可以,普通的数字验证码 from selenium import webdriver from PIL import Image import pytesseract ...