Scala-style-guide 建议在使用时始终明确定义返回类型 expect Unit
:
方法应根据以下模式声明:
def foo(bar: Baz): Bin = expr
此规则的唯一例外是返回 Unit 的方法。此类方法应使用 Scala 的语法糖以避免意外混淆返回类型:
def foo(bar: Baz) { // return type is Unit expr }
Scala-style-guide 建议在使用时始终明确定义返回类型 expect Unit
:
方法应根据以下模式声明:
def foo(bar: Baz): Bin = expr
此规则的唯一例外是返回 Unit 的方法。此类方法应使用 Scala 的语法糖以避免意外混淆返回类型:
def foo(bar: Baz) { // return type is Unit expr }
正如评论员所指出的,Martin Odersky 在链接的主题演讲中讨论了这一点。当然,正如“何时应该......”所表明的,这最终是一个文体问题,所以只能给出一个意见。
两件事:(1)类型是/否,以及(2)过程语法是/否。
(1) 显然,对于纯 API(没有实现),您必须指定返回类型。我会将其扩展到同时也是API的任何方法实现。即,如果你的方法没有实现一个特征——在这种情况下,当你的返回类型不同时编译器会给你一个错误——你应该注释这个方法。私有和本地方法都可以推断返回类型,除非您发现乍一看很难确定类型,或者您被迫(例如在递归方法调用中)。也有人说,当你给出明确的返回类型时,编译会更快。
如果您有具有“简单”返回类型的简短方法,我认为推理很好。前任。
trait Foo {
def sqrt(d: Double) = math.sqrt(d)
def toString = "Foo"
def bar = new Bar(123)
}
(但已经有人可能争辩说math.sqrt
返回 a可能并不明显Double
)。
虽然更冗长,但您可以使代码更具可读性,并且避免 (a)在超类型足够的情况下泄漏有关实现或子类型的信息:
trait Before {
def bar = new BarImpl
def seq = Vector(1, 2, 3)
}
trait After {
def bar: Bar = new BarImpl
def seq: IndexedSeq[Int] = Vector(1, 2, 3)
}
并且(b)您避免意外返回您不打算返回的东西,从结构类型到错误的集合类型等。
(2) 直到最近我更喜欢过程语法,但在重新讨论和许多人表达了他们的不满之后,我尝试使用显式: Unit =
注释,现在我更喜欢它了。我认为过程语法清楚地表明方法具有副作用,但确实: Unit =
也很清楚地表明了这一点。它还经常删除花括号的数量:
trait Before {
private var _x = 0
def x: Int = _x
def x_=(value: Int) { _x = value }
}
相对
trait After {
private var _x = 0
def x: Int = _x
def x_=(value: Int): Unit = _x = value // if double = confuses you, use new line?
}
我发现很多情况下正文以if
、模式match
、synchronized
块或future
生成、集合map
表达式等开头,在这些情况下删除花括号很好:
trait Before {
def connect()(implicit tx: Tx) {
values.foreach { case (x, _) =>
x.changed += this
}
}
}
trait After {
def connect()(implicit tx: Tx): Unit =
values.foreach { case (x, _) =>
x.changed += this
}
}