Scala 之旅

包中的顶级定义

语言

通常,在整个包中访问定义非常方便,并且不需要为包含它们的包装器 object 发明一个名称。

Scala 2 提供了 包对象,作为跨整个包共享的便捷容器。

包对象可以包含任意定义,而不仅仅是变量和方法定义。例如,它们经常用于保存包范围的类型别名和隐式转换。包对象甚至可以继承 Scala 类和特征。

在 Scala 3 的未来版本中,包对象将被顶级定义所取代。

根据惯例,包对象的源代码通常放在名为 package.scala 的源文件中。

每个包允许有一个包对象。放在包对象中的任何定义都被视为包本身的成员。

在 Scala 3 中,任何类型的定义都可以在包的顶级声明。例如,类、枚举、方法和变量。

放置在包顶层的任何定义都被视为包本身的成员。

在 Scala 2 中,顶层方法、类型和变量定义必须包装在包对象中。出于向后兼容性考虑,这些在 Scala 3 中仍然可以使用。您可以通过切换选项卡来查看它们的工作方式。

请参见下面的示例。假设首先在包 gardening.fruits 中有一个类 Fruit 和三个 Fruit 对象。

// in file gardening/fruits/Fruit.scala
package gardening.fruits

case class Fruit(name: String, color: String)
object Apple extends Fruit("Apple", "green")
object Plum extends Fruit("Plum", "blue")
object Banana extends Fruit("Banana", "yellow")

现在假设您想将变量 planted 和方法 showFruit 直接放置到包 gardening.fruits 中。以下是完成此操作的方法

// in file gardening/fruits/package.scala
package gardening
package object fruits {
  val planted = List(Apple, Plum, Banana)
  def showFruit(fruit: Fruit): Unit = {
    println(s"${fruit.name}s are ${fruit.color}")
  }
}
// in file gardening/fruits/package.scala
package gardening.fruits

val planted = List(Apple, Plum, Banana)
def showFruit(fruit: Fruit): Unit =
  println(s"${fruit.name}s are ${fruit.color}")

作为如何使用此方法的一个示例,以下程序以完全相同的方式导入 plantedshowFruit,因为它使用包 gardening.fruits 上的通配符导入导入类 Fruit

// in file PrintPlanted.scala
import gardening.fruits._

object PrintPlanted {
  def main(args: Array[String]): Unit = {
    for (fruit <- planted) {
      showFruit(fruit)
    }
  }
}
// in file printPlanted.scala
import gardening.fruits.*

@main def printPlanted(): Unit =
  for fruit <- planted do
    showFruit(fruit)

在包级别聚合多个定义

通常,您的项目可能在各个模块中定义了多个可重用定义,您希望在包的顶层聚合这些定义。

例如,在特征 FruitHelpers 中的一些帮助程序方法和在特征 FruitAliases 中的一些术语/类型别名。以下是将所有这些定义放在 fruit 包级别的方法

包对象就像其他对象一样,这意味着您可以使用继承来构建它们。因此,我们在此将帮助程序特征作为包对象的父级混合在一起。

package gardening

// `fruits` instead inherits its members from its parents.
package object fruits extends FruitAliases with FruitHelpers

在 Scala 3 中,最好使用 export 将多个对象中的成员组合到单个作用域中。在此,我们定义私有对象,将帮助程序特征混合在一起,然后在顶层导出其成员

package gardening.fruits

private object FruitAliases extends FruitAliases
private object FruitHelpers extends FruitHelpers

export FruitHelpers.*, FruitAliases.*

此页面的贡献者