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中进行了描述。