隐式引用(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进入我的博客主页

最新文章

  1. Silicon C8051F340之GPIO口配置与使用
  2. 从零开始调用一个手机号归属地查询API
  3. Hibernate之环境搭建及demo
  4. 【MVC 4】1.第一个 MVC 应用程序
  5. sql 中英文格式的时间转数字格式
  6. 导致Asp.Net站点重启的10个原因 ,记录重启原因
  7. securecrt 连接vmware ubuntu
  8. 动态规划---最长公共子序列 hdu1159
  9. Android 的独特shell命令
  10. 【转】jqGrid学习之安装
  11. SourceTree 基本介绍
  12. Logback日志基础配置以及自定义配置
  13. c# 向数据库插数据超过1000条
  14. 解决Tomcat version 7.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 and 6 Web modules
  15. elasticsearch开启外网访问
  16. centos7下安装docker(3.1创建镜像commit)
  17. saltstack 基本操作
  18. ling join 报错The specified LINQ expression contains references to queries that are associated with different cont
  19. 注解(Annotation)是什么?
  20. ubuntu 服务器配置

热门文章

  1. Ubuntu中vim添加lua支持
  2. 移动开发平台 apicloud、wex5
  3. flashcache 介绍
  4. ConstraintLayout 约束布局
  5. ef core 2.1 利用Query Type查询视图
  6. POI 2014 HOTELS (树形DP)
  7. OpenSSL使用3(基本原理及生成过程)(转)
  8. asp.net获取URL方法
  9. linux yum 安装软件
  10. 【FUN】——英文版面青年教育网站策划&GUI设计