作为评论员们所指出的,Martin Odersky在链接的主题演讲中讨论了这个问题。当然,“何时...”只是一个风格问题,因此只能提供意见。
两件事:(1) 类型是否需要明确,(2) 是否需要注释过程语法。
(1) 显然,对于纯API(没有实现的情况下),必须指定返回类型。我会将其扩展到任何同时也是API的方法实现。也就是说,如果您的方法不是实现特征,则应该注释该方法。私有和本地方法可以推断返回类型,除非您在第一眼难以确定类型,或者您被迫这样做(例如,在递归方法调用中)。还有人说,当你给出明确的返回类型时,编译速度更快。
(2) 如果您具有易于返回的简短方法,则认为推断是可以接受的。例如:
trait Foo {
def sqrt(d: Double) = math.sqrt(d)
def toString = "Foo"
def bar = new Bar(123)
}
(但是有人可能会争论,math.sqrt
返回一个 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
、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
}
}
Unit
作为返回类型还是省略它(编译器会自动推断类型)? - WelcomeTo