在scala中显式提供方法返回类型或变量类型的好处

时间:2015-02-14 07:14:14

标签: scala

这个问题可能非常愚蠢,但我有点困惑,这是scala中最好的方法。 在scala中,编译器执行类型推断并为每个变量或方法分配最接近(或可能是限制)类型。 我是scala的新手,从许多示例代码/库中,我注意到在许多地方,人们大多数时间都没有明确地提供类型。但是,在我编写的大多数代码中,我/仍然明确提供类型。例如:

val someVal: String = "def"

def getMeResult() : List[String]= {
  val list:List[String] = List("abc","def")
  list
}

我开始编写这个特别是方法返回类型的原因是,当我自己编写一个方法时,我知道它应该返回什么。所以如果我明确提供了返回类型,我可以知道我是否犯了任何错误。此外,我觉得通过阅读返回类型本身更容易理解该方法返回的内容。否则,我将检查最后一个语句的返回类型。

所以我的疑问/怀疑是: 1.由于编译器不必推断很多,编译时间是否较少?或者它并不重要? 2.斯卡拉世界的正常标准是什么?

4 个答案:

答案 0 :(得分:5)

来自“Scala in Depth”第4.5章

  

对于人类阅读一个非常重要的方法实现,推断出   返回类型可能会令人不安。最好明确记录和   在公共API中强制执行返回类型。

来自“Programming in Scala”第2章

  

有时Scala编译器会要求您指定结果   函数的类型。例如,如果函数是递归的,那么   必须明确指定函数的结果类型。

     

明确指出函数结果类型通常是个好主意。   这种类型的注释可以使代码更容易阅读,因为   读者无需研究功能体来弄清楚推断   结果类型。

来自“Scala in Action”第2.2.3节

  

为用户指定返回类型是一个好习惯   图书馆。如果你认为从功能中不清楚它的回归是什么   type是,尝试改进名称或指定返回类型。

来自“Programming Scala”第1章

  

递归函数是执行范围的一个例外   超出了正文的范围,所以返回类型必须是   声明。

     

对于简单的功能,也许展示它并不重要   明确。但是,有时推断的类型不会是什么   预期。显式返回类型提供了有用的文档   读者。我建议添加返回类型,尤其是在公共API中。

     

在以下情况下,您必须提供显式返回类型

     
      
  • 在方法中显式调用return时。
  •   
  • 当一个方法递归时。
  •   
  • 当两个或多个方法重载并且其中一个方法调用另一个方法时;调用方法需要返回类型注释。
  •   
  • 当推断的返回类型比您预期的更为通用时,例如,Any。
  •   

答案 1 :(得分:4)

其他答案中尚未提及的另一个原因如下。你可能知道program to an interface, not an implementation是个好主意。

对于函数或方法的返回值,这意味着您不希望函数或方法的用户知道函数返回的某个接口(或特征)的具体实现 - 这是您想要的实现细节隐藏。

如果你写这样的方法:

trait Example
class ExampleImpl1 extends Example { ... }
class ExampleImpl2 extends Example { ... }

def example() = new ExampleImpl1

然后该方法的返回类型将被推断为ExampleImpl1 - 因此,它暴露了它返回特征Example的特定实现的事实。您可以使用显式返回类型来隐藏它:

def example(): Example = new ExampleImpl1

答案 2 :(得分:2)

标准规则是使用API​​的显式类型(为了精确指定类型和防止重构)以及implicits(特别是因为如果定义站点位于后面,则可以忽略没有显式类型的implicits使用网站)。

对于第一个问题,类型推断可能是一个重要的税收,但这与写作和阅读表达的容易性相平衡。

在示例中,本地列表上的类型甚至不是“更好的java”。这只是视觉上的混乱。

但是,应该很容易阅读推断类型。偶尔,我必须启动IDE才能告诉我推断的内容。

通过暗示,方法应该足够短,以便于扫描结果类型。

很抱歉缺少参考资料。也许别人会挺身而出; MLs和SO上经常出现这个话题。

答案 3 :(得分:1)

2。 scala style guide

  

尽可能使用类型推断,但首先要明确,并在公共API中支持显式。

     

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

private val name = "Daniel"
  

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

     

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

twitter scala style guide说方法返回类型:

  

虽然Scala允许省略这些注释,但这样的注释提供了良好的文档:这对于公共方法尤其重要。如果方法没有暴露且返回类型明显,则省略它们。

我认为广泛的共识是显式类型应该用于公共API,并且不应该用于大多数局部变量声明。何时使用显式类型"内部"方法不那么明确,更多的是判断问题;不同的组织有不同的标准。

1。类型推断似乎并没有明显影响推理发生的行的编译时间(除了一些基本上是编译器错误的隐含的罕见情况) - 毕竟,编译器仍然需要检查类型,这是用来推断它的计算几乎相同。但是,如果推断出方法返回类型,那么当该方法发生更改时,必须重新编译使用该方法的任何内容。

因此,推断在许多地方使用的方法(或公共变量)会降低编译速度(特别是如果您使用增量编译)。但推断仅在一个或两个地方使用的本地或私人变量,私有方法或公共方法,不会产生(重大)差异。