先来看一下下面的内容:

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 - 隐式类型转换的更多相关文章

  1. Scala学习二十一——隐式转换和隐式参数

    一.本章要点 隐式转换用于类型之间的转换 必须引入隐式转换,并确保它们可以以单个标识符的形式出现在当前作用域 隐式参数列表会要求指定类型的对象.它们可以从当前作用域中以单个标识符定义的隐式对象的获取, ...

  2. Scala 学习笔记之隐式参数和隐式转换并用

    隐式转换条件: 1. 当表达式类型与预期的类型不同时 2.当对象访问一个不存在的成员时 3.当对象调用某个方法,而该方法的参数声明与传入参数不相匹时. 隐式转换搜索范围: 1. 位于源火目标类型伴生对 ...

  3. JavaScript学习总结(二、隐式类型转换、eval())

    一.(避免)隐式类型转换 console.log(false == 0);   //logs true; console.log(false === 0);   //logs false; conso ...

  4. Scala进阶之路-Scala高级语法之隐式(implicit)详解

    Scala进阶之路-Scala高级语法之隐式(implicit)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们调用别人的框架,发现少了一些方法,需要添加,但是让别人为你一 ...

  5. C++的隐式类型转换

    C++是一种复杂的语言,其中有许多“好玩”的特性,学习C++的过程就像在海边捡一颗颗石头,只要坚持不懈,也许一颗颗小石头也能建起你自己小小的城堡. 废话完后,讲讲自己捡到的石头:隐式类型转换 学习出处 ...

  6. 深入js隐式类型转换

    前言 相信刚开始了解js的时候,都会遇到 2 =='2',但是 1+'2' == '1'+'2'为false的情况,这时候应该会是一脸懵逼的状态,不得不感慨js弱类型的灵活让人发指,隐式类型转换就是这 ...

  7. javascript的隐式类型转换

    首先简单了解js的typeof,会返回六种类型 即 number string boolen function object undefined 也就是六种基本数据类型 显示类型转换大概有以下几种: ...

  8. js条件判断时隐式类型转换

    Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...

  9. dynamic_cast 和 static_cast 隐式类型转换的区别

    首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...

随机推荐

  1. 160630、五句话搞定JavaScript作用域

    JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕.   一.“JavaScript中无块级作用域” 在Java或C# ...

  2. java编程思想 英文版 打卡

    计划 2017.3.1 购入 准备花一个月的时间阅读完, 共1500页,最后两章是GUI的内容,只需要到1300页就行了 目的有三: 熟悉java基础 提升英语阅读能力,好久没读英文书籍了 补补oop ...

  3. 搭建SVN和eclipse添加svn插件

    在ubuntu服务器下安装svn服务器端,在window下使用eclipse的svn插件团队开发. 安装SVN服务端 1.在ubuntu上安装svn服务器 sudo apt-get install s ...

  4. MVC异步消息推送机制

    在MVC里面,有异步控制器,可以实现模拟消息推送机制功能 1.控制器要继承至AsyncController,如 public class RealTimeController : AsyncContr ...

  5. Ubuntu 14.04下安装GitLab

    0.硬件要求 官方要求:http://doc.gitlab.com/ce/install/requirements.html CPU 1 core works supports up to 100 u ...

  6. pytho创建二维码简单版

    pytho创建二维码简单版 import qrcode aa = qrcode.make("https://github.com/phygerr/") aa.save('C:\Us ...

  7. Uber中国在地方城市的人员架构是怎样的?

    http://www.thepaper.cn/newsDetail_forward_1390516 澎湃新闻:Uber中国在地方城市的人员架构是怎样的?   柳甄:一般是3人组成的小团队作战.一名城市 ...

  8. React:快速上手(1)——基础知识

    React:快速上手(1)——基础知识 React(有时叫React.js或ReactJS)是一个为数据提供渲染为HTML视图的开源JavaScript库,用于构建用户界面. JSX.元素及渲染 1. ...

  9. LeetCode:N叉树的后序遍历【590】

    LeetCode:N叉树的后序遍历[590] 题目描述 给定一个 N 叉树,返回其节点值的后序遍历. 例如,给定一个 3叉树 : 返回其后序遍历: [5,6,3,2,4,1]. 题目分析 这道题有好几 ...

  10. LeetCode:括号的分数【856】

    LeetCode:括号的分数[856] 题目描述 给定一个平衡括号字符串 S,按下述规则计算该字符串的分数: () 得 1 分. AB 得 A + B 分,其中 A 和 B 是平衡括号字符串. (A) ...