跳轉到內容

Scala/包

來自華夏公益教科書

包是一個組織單元,可以包含類、物件和其他包等實體。包含在給定包中的實體屬於該包的名稱空間。

請注意,以下示例可能無法在 Scala REPL 中執行。

包可以在原始檔的開頭宣告

package geometry

class Rectangle

在第一行,關鍵字“package”後跟名稱“geometry”聲明瞭一個名為“geometry”的包。所有後續實體都屬於該包。在第三行,定義了一個名為“Rectangle”的類,由於它在“geometry”包中宣告,因此它的完整識別符號為“geometry.Rectangle”。

可以透過在每個包之間插入“.”來宣告多個巢狀包

package org.transport.vehicles

class Car

在第一行,聲明瞭巢狀包“org”、“transport”和“vehicles”。“org”是最外層的包,“transport”是最中間的包,“vehicles”是最內層的包。在第三行,定義了一個名為“Car”的類,它的完整識別符號為“org.transport.vehicles.Car”。

類似的方法是將包連結起來

package org
package transport
package vehicles

class Car

這聲明瞭 3 個巢狀包和一個名為“Car”的類,其完整識別符號為“org.transport.vehicles.Car”。

包也可以透過在包名後跟一對花括號來在原始碼中的其他地方宣告

package org.transport

package vehicles {
  class Car
}

package fuel {
  class Gasoline
}

第一行定義了巢狀包“org.transport”。第 3 到 5 行定義了一個屬於“org.transport”的包,名為“vehicles”,它包含類“Car”。第 7 到 9 行定義了一個屬於“org.transport”的包,名為“fuel”,它包含類“Gasoline”。類“Car”的完整識別符號為“org.transport.vehicles.Car”,類 Gasoline 的完整識別符號為“org.transport.fuel.Gasoline”。

一個名稱空間中的實體通常不能直接引用另一個名稱空間中的實體,除非使用完整識別符號

package somePack1 {
  class SomeClass
}
package somePack2 {
  class AnotherClass {
    val a = new somePack1.SomeClass
    //ERROR: Does not compile!
    //val b = new SomeClass
  }
}

在某些情況下,不同名稱空間中的實體可以在不使用完整識別符號的情況下相互引用。一種情況是在引用層次結構中上層包中的實體時。規則是,對於每個巢狀宣告中的最後一部分的實體,所有宣告的包都可以直接引用。

package p1.p2.p3

class A

package p4 {
  class B
}

package p4 {
  package p5 {
    class C
  }

  package p5.p6 {
    class D {
      val a = new A
      val b = new B
      val c = new p5.C
      //ERROR: Does not compile!
      //val c2 = new C
    }
  }
}

在上面,聲明瞭幾層包。最底層的包“p6”包含一個名為“D”的類。對於類“D”,它的包宣告可以總結為“p1.p2.p3”、“p4”和“p5.p6”。由於包“p3”、“p4”和“p6”是“D”的每個包宣告的最後部分,因此所有成員都可以直接在“D”中引用。相反,在“p1”、“p2”和“p5”中的實體無法直接引用。這有助於對哪些實體可以或不能直接引用進行細粒度控制。預設方法是將包宣告在一個宣告中,這意味著只有當前包中的實體可以被直接引用。

下層巢狀包會覆蓋上層包。這意味著在某些情況下,引用特定實體可能很困難。在這種情況下,可以使用特殊包“_root_”。所有頂級包都被視為“_root_”的成員

package tools {
  class Console
}

package carpentry {
  package tools {
    class Hammer

    package testing {
      class A {
        val console = new _root_.tools.Console
        //ERROR: Does not compile!
        //val console2 = new tools.Console
      }
    }
  }
}

在上面,從類“A”的角度來看,包“tools”指的是“carpentry.tools”包,因為它覆蓋了“tools”包。為了引用最外層的“tools”包,使用了包“_root_”。

需要注意的是,不同包中的實體通常可以透過使用匯入來更輕鬆地引用,這在Scala/Import中進行了描述。

華夏公益教科書