英文原文:​http://docs.scala-lang.org/style/

译文如下:


一、接口

在可能的情况下使用类型推断,但首先要清楚,并且在公共API中有利于明确。

您几乎不应该注释私有字段或本地变量的类型,因为它们的类型通常会立即显示在其值中:

private val name = "Daniel"

但是,您可能希望仍然显示分配值具有复杂或非显而易见形式的类型。

所有公共方法都应该有明确的类型注释。在这些情况下,类型推断可能会破坏封装,因为它取决于内部方法和类详细信息。没有明确的类型,对方法或值的内部结构的更改可能会改变类的公共API而不发出警告,从而潜在地破坏客户端代码。显式类型注释也有助于提高编译时间。

函数值

函数值支持类型推断的特殊情况,值得自行调用:

val ls: List[String] = ...
ls map (str => str.toInt)

在Scala已经知道我们声明的函数值的类型的情况下,不需要注释参数(在这种情况下 ​​str​​)。这是一个非常有帮助的推论,应该尽可能优先。请注意,对函数值进行操作的隐式转换将使该推断无效,强制显式注释参数类型。

二、注释

类型注释应根据以下模板进行图案化:

value: Type

这是Scala大多数标准库和Martin Odersky所有例子所采用的风格。值和类型之间的空间有助于准确解析语法。将冒号放置在值的末尾而不是类型的开始的原因是为了避免在这种情况下的混淆:

value :::

这实际上是有效的Scala,声明一个值为类型​​::​​。显然,前缀风格的注解冒号大大地混乱了事情。

三、归属

类型归属通常与类型注释混淆,因为Scala中的语法相同。以下是归属的例子:

​Nil: List[String]​​​​Set(values: _*)​​​​"Daniel": AnyRef​​解决方案基本上只是在编译时为了类型检查器而进行的升级。它的使用并不常见,但它有时会发生。最常见的归因情况是使用单个​​Seq​​参数调用varargs方法。这是通过归纳​​_*​​类型来完成的(如上面的第二个例子)。

Ascription遵循类型注释约定; 冒号后面有一个空格。


四、函数

应该使用参数类型,箭头和返回类型之间的空格声明函数类型:

def foo(f: Int => String) = ...

def bar ( f : ( Boolean , Double ) => List [ String ]) = ...应尽可能省略括号(例如,arity-1的方法,如​​Int => String​​)。

元数-1

Scala具有用于声明arity-1功能的类型的特殊语法。例如:

def map[B](f: A => B) = ...

具体来说,括号可以从参数类型中省略。因此,我们并没有声明​​f​​是类型的​​(A) => B​​,因为这将是不必要的冗长。考虑更极端的例子:

// wrong!
def foo(f: (Int) => (String) => (Boolean) => Double) = ...

// right! def foo ( f : Int => String => Boolean => Double ) = ...

通过省略括号,我们保存了六个全部字符,并大大提高了类型表达式的可读性。

五、结构类型

如果结构类型的长度小于50个字符,则应在单行上声明。否则,它们应该分割成多行,(通常)分配给自己的类型别名:

// wrong!
def foo(a: { def bar(a: Int, b: Int): String; val baz: List[String => String] }) = ...

// right! private type FooParam = { val baz : List [ String => String ] def bar ( a : Int , b : Int ): String } def foo ( a : FooParam ) = ...

更简单的结构类型(不超过50个字符)可以被声明和使用内联:

def foo(a: { val bar: String }) = ...

在内部声明结构类型时,每个成员应该用分号和单个空格分开,开放大括号后面应该有 一个空格,而关闭大括号应该在前面加上一个空格(如上面两个例子所示)。

结构类型在运行时通过反射来实现,并且本质上比标称类型的性能更差。开发商应优先使用名义类型,除非结构类型提供明确的收益。