通常情况下,文件应包含一个单个逻辑编译单元。我所说的“逻辑”是指类、特质或对象。此准则的一个例外是具有伴生对象的类或特质。伴生对象应与其对应的类或特质分组在同一文件中。这些文件应根据它们包含的类、特质或对象进行命名
package com.novell.coolness
class Inbox { ... }
// companion object
object Inbox { ... }
这些编译单元应放置在 com/novell/coolness
目录中的名为 Inbox.scala
的文件中。简而言之,应优先考虑 Java 文件命名和定位约定,尽管 Scala 在这方面允许更大的灵活性。
多单元文件
尽管有上述说法,但有一些重要情况需要在一个文件中包含多个编译单元。一个常见的例子是密封特质和几个子类(通常模拟函数式语言中可用的 ADT 语言特性)
sealed trait Option[+A]
case class Some[A](a: A) extends Option[A]
case object None extends Option[Nothing]
由于密封超类(和特质)的性质,所有子类型必须包含在同一文件中。因此,这种情况绝对符合应忽略对单单元文件偏好的情况。
另一种情况是当多个类在逻辑上形成一个单一的、内聚的组,共享概念,以至于将它们包含在一个文件中对维护非常有益。与上述密封超类型异常相比,这些情况更难预测。一般来说,如果在单个文件中对多个单元进行长期维护和开发更容易,而不是分散在多个单元中,那么对于这些类应优先采用这种组织策略。但是,请记住,当多个单元包含在一个文件中时,在需要进行更改时通常更难找到特定单元。
所有多单元文件应采用小写开头字母的驼峰式命名。这是一条非常重要的约定。它将多单元文件与单单元文件区分开来,极大地简化了查找声明的过程。这些文件名可以基于它们包含的重要类型(例如,上面示例中的 option.scala
),或者可以描述其中所有单元共享的逻辑属性(例如,ast.scala
)。