【Scala】Scala之Packaging and Imports

leesf發表於2017-04-11

一、前言

  前面介紹了Scala的Object,由於中間論文的時間耽誤了些時間,接著繼續學習Scala的Packaging和Imports

二、Packaging and Imports

  Scala的包用法與Java類似,但更靈活。在class檔案頂端使用package語法,並且可以使用帶中括號的package語法,與Java相比,Scala的匯入有如下特點

    · 可在任何地方使用import宣告

    · 可匯入類、包、物件

    · 對匯入的成員隱藏或者重新命名

  並且在Scala中,隱式匯入了java.lang._和scala.lang._兩個包,_與Java中的*一樣,表示匯入包下所有的類,除了上述兩個包,scala.Predef物件也被隱式匯入,可以詳細閱讀Predef的原始碼,裡面包含了很多Scala的語法

  2.1 帶有中括號符號的包

  1. 問題描述

  你想使用一個巢狀風格的包符號,類似於C++和C#名稱空間的符號

  2. 解決方案

  將類放置在有中括號的包名中,如下所示 

package com.hust.grid {
    class Foo { override def toString = "I am com.hust.grid.Foo" }
}

  類的規範名字是com.hust.grid.Foo,其等效於如下程式碼

package com.hust.grid 

class Foo { override def toString = "I am com.hust.grid.Foo" }

  使用這種方法,可以在一個檔案中放置多個package,也可以使用“中括號”風格巢狀包

  下面示例展示了三個不同的Foo類,Foo類在不同的包中  

// a package containing a class named Foo
package orderentry {
    class Foo { override def toString = "I am orderentry.Foo" }
}

// one package nested inside the other
package customers {
    class Foo { override def toString = "I am customers.Foo" }
    
    package database {
        // this Foo is different than customers.Foo or orderentry.Foo
        class Foo { override def toString = "I am customers.database.Foo" }
    }
}

// a simple object to test the packages and classes
object PackageTests extends App {
    println(new orderentry.Foo)
    println(new customers.Foo)
    println(new customers.database.Foo)
}

  輸出結果如下 

I am orderentry.Foo
I am customers.Foo
I am customers.database.Foo

  3. 討論

  可以使用在檔案頂端宣告包名,但是也可以使用帶中括號風格的包名來將多個類和包放置在同一個檔案下

  2.2 匯入一個或多個成員

  1. 討論

  你想要將一個或多個成員匯入到當前程式的作用域中

  2. 解決方案

  下面是匯入一個類的語法 

import java.io.File

  你可以匯入多個類 

import java.io.File
import java.io.IOException
import java.io.FileNotFoundException

  或者使用Scala的匯入方式 

import java.io.{File, IOException, FileNotFoundException}

  或者匯入java.io包下所有的類  

import java.io._

  _與Java中的萬用字元*含義相同

  3. 討論

  Scala的匯入比Java更的使用為靈活,在Scala中,你可以在任何地方放置匯入申明,如Scala檔案中可包含多個類或者包,此時,可以在不同的包中宣告匯入,使得具有不同的作用域 

package foo

import java.io.File
import java.io.PrintWriter

class Foo {
    import javax.swing.JFrame // only visible in this class
    // ...
}

class Bar {
    import scala.util.Random // only visible in this class
    // ...
}

  你甚至可以在方法中、函式中、程式碼塊中放置匯入申明

class Bar {
    def doBar = {
        import scala.util.Random
        println("")
    }
}

  2.3 對匯入成員重新命名

  1. 問題描述

  在匯入成員時重新命名成員以避免名稱空間衝突或混淆

  2. 解決方案

  使用下面語法將成員進行重新命名  

import java.util.{ArrayList => JavaList}

  在程式碼中,可以使用如下方式使用 

val list = new JavaList[String]

  也可以一次性重新命名多個類 

import java.util.{Date => JDate, HashMap => JHashMap}

  當進行重新命名後,之前的名字不能正常使用 

// error: this won't compile because HashMap was renamed
// during the import process
val map = new HashMap[String, String]

  3. 討論

  重新命名成員可以名稱空間衝突或混淆 

import java.util.{HashMap => JavaHashMap}
import scala.collection.mutable.{Map => ScalaMutableMap}

  你不僅可以重新命名類,也可以重新命名類的成員,如方法

  

  2.4 在匯入時隱藏類

  1. 問題描述

  當從同一包匯入其他成員時,你想要隱藏一個或多個類

  2. 解決方案

  其類似於重新命名,但是使用_符號代替重新命名的名字,如下面示例隱藏了Random類,但是匯入了java.util中的所有其他類

import java.util.{Random => _, _}

  其中,第一個_符號代表隱藏Random類,第二個_符號程式碼匯入所有的其他類,並且匯入萬用字元必須要放在最後,否則發生錯誤

  

  若需要隱藏多個成員,可以使用如下做法

import java.util.{List => _, Map => _, Set => _, _}

  2.5 使用靜態匯入

  1. 問題描述

  你想要像Java靜態匯入那樣匯入成員,以便可以直接使用成員名字,而不需要加類名的字首

  2. 解決方案

  使用下面方法匯入java.Math中所有的成員

import java.lang.Math._

  此時,你就可以不需要加字首來使用Math類中的成員

  

  2.6 在任何地方使用Import申明

  1. 問題描述

  你想要在任何地方使用import申明,以便控制作用域和管理程式碼

  2. 解決方案

  你可以在類定義之前使用匯入,然後在類中使用

package foo

import scala.util.Random

class ImportTests {
    def printRandom {
        val r = new Random
    }
}

  也可以在類中匯入 

package foo

class ImportTests {
    import scala.util.Random
    def printRandom {
        val r = new Random
    }
}

  這使得import的作用域在類中,也可以將import的作用域限制在方法中 

def getRandomWaitTimeInMinutes: Int = {
    import com.alvinalexander.pandorasbox._
    val p = new Pandora
    p.release
}

  還可以將import作用域控制在程式碼塊中

def printRandom {
    {
        import scala.util.Random
        val r1 = new Random // this is fine
    }
    val r2 = new Random // error: not found: type Random
}

  3. 討論

  import是按照順序讀取的,放置import的位置也決定了其作用域

// this doesn't work because the import is after the attempted reference
class ImportTests {
    def printRandom {
        val r = new Random // fails
    }
}
import scala.util.Random

  當檔案中包含多個類和包時,你可以結合import申明和包引入方法來限制import語句的作用域

package orderentry {
    import foo._
    // more code here ...
}

package customers {
    import bar._
    // more code here ...
    package database {
        import baz._
        // more code here ...
    }
}

三、總結

  本篇博文講解了Scala中的包和匯入方面的知識點,最主要的就是作用域問題,知識點也相對簡單,也謝謝各位園友的觀看~

相關文章