zoukankan      html  css  js  c++  java
  • 【Scala】Scala的Predef对象

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

  • 相关阅读:
    分布式系统中的Session问题
    HotSpot VM运行时---命令行选项解析
    K大数查询
    [DarkBZOJ3636] 教义问答手册
    小朋友和二叉树
    [COCI2018-2019#2] Sunčanje
    小SY的梦
    [HDU6722 & 2019百度之星初赛四 T4] 唯一指定树
    [HDU6800] Play osu! on Your Tablet
    [NOI2007] 货币兑换
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7224101.html
Copyright © 2011-2022 走看看