Scala 包和引用
1.包/作用域
在Java和Scala中管理專案可以使用包結構,C和C#使用名稱空間。
對於package,有如下幾種形式:
形式體現:
package com.nick.impatient.people
class Person{
val name = "Nick"
def play(message: String): Unit ={
}
}
等同於:
package com.nick.impatient package people class Person{ val name = "Nick" def play(message: String): Unit ={ } }
等同於:
package com.nick.impatient{// com和com.nick的成員在這裡不可見
package people{
class Person{
val name = "Nick"
def play(message: String): Unit ={
}
}
}
}
注:位於檔案頂部不帶花括號的包宣告在整個檔案範圍內有效。
通過以上形式,發出總結:
(1)包也可以像內部類那樣巢狀,作用域原則:可以直接向上訪問。即,子package中直接訪問父package中的內容。(即:作用域
(2)包物件可以持有函式和變數
(3)引入語句可以引入包、類和物件
(4)原始檔的目錄和包之間並沒有強制的關聯關係
(5)可以在同一個.scala檔案中,宣告多個並列的package
(6)包名可以相對也可以絕對,比如,訪問ArrayBuffer的絕對路徑是:_root_.scala.collection.mutable.ArrayBuffer
2.包物件
包可以包含類、物件和特質trait,但不能包含函式或變數的定義。很不幸,這是Java虛擬機器的侷限。把工具函式或常量新增到包而不是某個Utils物件,這是更加合理的做法。包物件的出現正是為了解決這個侷限。每個包都可以有一個包物件。你需要在父包中定義它,且名稱與子包一樣。
package com.nick.impatient
package object people {
val defaultName = "Nick"
}
package people {
class Person {
var name = defaultName // 從包物件拿到的常置
}
}
3.包可見性
在Java中,沒有被宣告為public、private或protected的類成員在包含該類的包中可見。在Scala中,你可以通過修飾符達到同樣的效果。以下方法在它自己的包中可見:
package com.nick.impatient.people
class Person {
private[people] def description="人的名字:" + name
}
當然,也可以將可見度延展到上層包:
private[impatient] def description="人的名字:" + name
4.引入
在Scala中,import語句可以出現在任何地方,並不僅限於檔案頂部。import語句的效果一直延伸到包含該語句的塊末尾:這是個很有用的特性,尤其是對於通配引入而言。從多個源引入大量名稱總是讓人擔心。事實上,有些Java程式設計師特別不喜歡通配引入,以至於從不使用這個特性,而是讓IDE幫他們生成一長串引入語句。通過將引入放置在需要這些引入的地方,你可以大幅減少可能的名稱衝突。
5.重新命名和隱藏方法
(1) 重新命名:
如果你想要引人包中的幾個成員,可以像這樣使用選取器( selector),而且選取的同時,可以重新命名:
import java.util.{ HashMap=>JavaHashMap, List}
import scala.collection.mutable._
這樣一來,JavaHashMap就是java.utiI.HashMap,而HashMap則對應scala.collection.mutable.HashMap。
(2)隱藏:
選取器HashMap =>_將隱藏某個成員而不是重新命名它。這僅在你需要引入其他成員時有用:
import java.util.{HashMap=>_, _ }
import scala.collection.mutable._
現在,HashMap很明確的便指向了scala.collection.mutable.HashMap,因為java.util.HashMap被隱藏起來了。
注:
每個Scala程式都隱式地以如下程式碼開始:
import java.lang._
import scala._
import Predef._
和Java程式一樣,java.lang總是被引入。接下來,scala包也被引入,不過方式有些特殊。不像所有其他引入,這個引入被允許可以覆蓋之前的引入。舉例來說,scala.StringBuilder覆蓋java.lang.StringBuilder而不是與之衝突。最後,Predef物件被引入。它包含了相當多有用的函式,這些同樣可以被放置在scala包物件中,不過Predef在Scala還沒有加入包物件之前就存在了。
由於scala包預設被引入,對於那些以scala開頭的包,你完全不需要寫全這個字首。例如:
collection.mutable.HashMap
上述程式碼和以下寫法一樣好:
scala.collection.mutable. HashMap