隐式引用(Implicit Import)

Scala会自己主动为每一个程序加上几个隐式引用,就像Java程序会自己主动加上java.lang包一样。

Scala中。下面三个包的内容会隐式引用到每一个程序上。所不同的是。Scala还会隐式加进对Predef的引用。这极慷慨便了程序猿的工作。

import java.lang._ // in JVM projects, or system namespace in .NET
import scala._ // everything in the scala package
import Predef._ // everything in the Predef object

上面三个包,包括了经常使用的类型和方法。java.lang包包括了经常使用的java语言类型,假设在.NET环境中,则会引用system命名空间。相似的,scala还会隐式引用scala包,也就是引入经常使用的scala类型。

请注意

上述三个语句的顺序藏着一点玄机。

我们知道,通常,假设import进来两个包都有某个类型的定义的话,比方说,同一段程序。即引用了’scala.collection.mutable.Set’又引用了’import scala.collection.immutable.Set’则编译器会提示无法确定用哪一个Set。

这里的隐式引用则不同,假设有同样的类型。后面的包的类型会将前一个隐藏掉。

比方。java.lang和scala两个包里都有StringBuilder。这样的情况下,会使用scala包里定义的那个。java.lang里的定义就被隐藏掉了,除非显示的使用java.lang.StringBuilder。

Predef对象

Predef提供经常使用函数

包scala中的Predef对象包括了很多实用的方法。比如,Scala源文件里写下println语句,实际调用的是Predef的println。Predef.println转而调用Console.println,完整真正的工作。

def print(x: Any) = Console.print(x)
def println() = Console.println()
def println(x: Any) = Console.println(x)
def printf(text: String, xs: Any*) = Console.print(text.format(xs: _*))

断言函数assert以及相关函数也是在Predef中定义的:

/** Tests an expression, throwing an `AssertionError` if false.
* Calls to this method will not be generated if `-Xelide-below`
* is at least `ASSERTION`.
*
* @see elidable
* @param assertion the expression to test
*/
@elidable(ASSERTION)
def assert(assertion: Boolean) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed")
} /** Tests an expression, throwing an `AssertionError` if false.
* Calls to this method will not be generated if `-Xelide-below`
* is at least `ASSERTION`.
*
* @see elidable
* @param assertion the expression to test
* @param message a String to include in the failure message
*/
@elidable(ASSERTION) @inline
final def assert(assertion: Boolean, message: => Any) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed: "+ message)
}

Predef定义类型别名

Predef是一个对象(Object)。这个对象中,定义一些类型别名。如:

scala.collection.immutable.List         // to force Nil, :: to be seen.

type Function[-A, +B] = Function1[A, B]

type Map[A, +B] = immutable.Map[A, B]
type Set[A] = immutable.Set[A]
val Map = immutable.Map
val Set = immutable.Set

如今我们知道了。直接使用集合时,如List。Map。Set。用到的是immutable包中的对象。这是在Predef里定义的。

隐式转换

Predef对象定义了经常使用的隐式转换,如:

implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}

该隐式转换。给AnyVal的全部子类型都加上了+(other: String): String方法,便于在打印或其它字符串操作时,增加其它的值类型。

再如:

@inline implicit def augmentString(x: String): StringOps = new StringOps(x)
@inline implicit def unaugmentString(x: StringOps): String = x.repr

该隐式转换,使得我们能够自由的对String使用StringOps的方法。

同理,数值类型的富包装(Rich Wrapper)也是这样实现的。

Scala程序猿能够较少关心装箱和拆箱操作,这也是因为Predef对象里定义了Scala值类型与java基本类型直接的隐式转换。

implicit def byte2Byte(x: Byte)           = java.lang.Byte.valueOf(x)
implicit def short2Short(x: Short) = java.lang.Short.valueOf(x)
implicit def char2Character(x: Char) = java.lang.Character.valueOf(x)
implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x)
implicit def long2Long(x: Long) = java.lang.Long.valueOf(x)
implicit def float2Float(x: Float) = java.lang.Float.valueOf(x)
implicit def double2Double(x: Double) = java.lang.Double.valueOf(x)
implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue
implicit def Short2short(x: java.lang.Short): Short = x.shortValue
implicit def Character2char(x: java.lang.Character): Char = x.charValue
implicit def Integer2int(x: java.lang.Integer): Int = x.intValue
implicit def Long2long(x: java.lang.Long): Long = x.longValue
implicit def Float2float(x: java.lang.Float): Float = x.floatValue
implicit def Double2double(x: java.lang.Double): Double = x.doubleValue
implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue

关于装箱(Boxing)和拆箱(Unboxing)

熟悉Java或C#等语言的读者会知道,装箱是指将原始类型转换成引用类型(对象)。用于须要对象的操作,而拆箱,则是把对象转换成原始类型,用于须要原始类型的场景。

因为数值类型本身已经是类对象,因此Scala里不须要装箱(boxing)和拆箱(unboxing)操作。

当然,Scala代码终于会执行在JVM上,所以实际上,始终会有装箱成Scala类对象,和拆箱成Java原始值类型的操作,可是这些操作是透明的,程序猿不须要关心(实际上,这是由定义在Predef中的隐式转换完毕的)。

參考资料

Predef官方标准库文档

隐式引用(Implicit Import)和Predef

转载请注明作者Jason Ding及其出处

GitCafe博客主页(http://jasonding1354.gitcafe.io/)

Github博客主页(http://jasonding1354.github.io/)

CSDN博客(http://blog.csdn.net/jasonding1354)

简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)

Google搜索jasonding1354进入我的博客主页

【Scala】Scala的Predef对象的更多相关文章

  1. Scala 编程---类和对象

    类是对象的蓝图.一旦你定义了类,你就可以用关键字new从类的蓝图里创建对象.比方说,如果给出了类的定义: class ChecksumAccumulator { // class definition ...

  2. Scala:类,对象和特征(接口)

    http://blog.csdn.net/pipisorry/article/details/52902609 Scala类和对象 类是对象的抽象,而对象是类的具体实例.类是抽象的,不占用内存,而对象 ...

  3. [Scala]Scala学习笔记五 Object

    1. 单例对象 Scala没有静态方法或静态字段,可以使用object来达到这个目的,对象定义了某个类的单个实例: object Account{ private var lastNumber = 0 ...

  4. Scala之类型参数和对象

    泛型 类型边界 视图界定 逆变和协变 上下文界定 源代码 1.泛型 泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性, 使用泛型可以使得类或方法具有更 ...

  5. scala学习-类与对象

    类 / 对象 [<快学Scala>笔记] 一.类 1.Scala中的类是公有可见性的,且多个类可以包含在同一个源文件中: class Counter{ private var value ...

  6. 快学Scala 第6章 对象 - 练习

    1. 编写一个Conversions对象,加入inchesToCentimeters.gallonsToLiters和milesToKilometers方法. object Conversions { ...

  7. Scala学习笔记——函数式对象

    用创建一个函数式对象(类Rational)的过程来说明 类Rational是一种表示有理数(Rational number)的类 package com.scala.first /** * Creat ...

  8. Scala学习之路 (六)Scala的类、对象、继承、特质

    一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...

  9. scala中json与对象的转换

    遇到的问题 因为要把spark从es读出来的json数据转换为对象,开始想用case class定义类型,通过fastjson做转换.如下 case class Book (author: Strin ...

随机推荐

  1. 多线程设计模式 : Master-Worker模式

    Master-Worker是常用的并行计算模式.它的核心思想是系统由两类进程协作工作:Master进程和Worker进程.Master负责接收和分配任务,Worker负责处理子任务.当各个Worker ...

  2. LeetCode OJ-- Length of Last Word

    https://oj.leetcode.com/problems/length-of-last-word/ 对一个字符串遍历,求最后一个单词的长度,如果有 ‘ ’,则切开了. 字符串的最后一个字符为 ...

  3. iOS YYYY 和 yyyy的区别

    2017年1月31日 转换后变成 2018年1月31日,相差一年.这是为什么呢? 原因:YYYY 是以周为单位计算的,我们平常计算日期时最好用yyyy,yyyy才是标注的年份 如果一月1日是星期一,星 ...

  4. centos7.2安装tomcat8

    环境: 阿里云centos7.2 tomcat8.0.32 jdk8.131 1 上传tomcat安装包到服务器的/home(个人习惯) 2 解压安装包 [root@iZt4n6h3u4k407nni ...

  5. HDU 4343 Interval query(贪心 + 倍增)

    题目链接  2012多校5 Problem D 题意  给定$n$个区间,数字范围在$[0, 10^{9}]$之间,保证左端点严格大于右端点. 然后有$m$个询问,每个询问也为一个区间,数字范围在$[ ...

  6. 洛谷——P1617 爱与愁的一千个伤心的理由

    P1617 爱与愁的一千个伤心的理由 题目背景 (本道题目隐藏了两首歌名,找找看哪~~~) <爱与愁的故事第一弹·heartache>第二章. 经历了心痛后,爱与愁大神不行了. 题目描述 ...

  7. codevs——1220 数字三角形(棋盘DP)

     时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 如图所示的数字三角形,从顶部出发,在每一结点可以选择向左走或 ...

  8. luogu P1336 最佳课题选择

    题目描述 Matrix67要在下个月交给老师n篇论文,论文的内容可以从m个课题中选择.由于课题数有限,Matrix67不得不重复选择一些课题.完成不同课题的论文所花的时间不同.具体地说,对于某个课题i ...

  9. [TJOI2014] Alice and Bob

    非常好的一道思维性题目,想了很久才想出来qwq(我好笨啊) 考虑a[]数组有什么用,首先可以yy出一些性质 (设num[i]为原来第i个位置的数是什么 , 因为题目说至少有一个排列可以满足a[],所以 ...

  10. Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储

    Python爬虫可以说是好玩又好用了.现想利用Python爬取网页股票数据保存到本地csv数据文件中,同时想把股票数据保存到MySQL数据库中.需求有了,剩下的就是实现了. 在开始之前,保证已经安装好 ...