简体   繁体   English

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

[英]Benefit of explicitly providing the method return type or variable type in scala

This question may be very silly, but I am a little confused which is the best way to do in scala. 这个问题可能非常愚蠢,但我有点困惑,这是scala中最好的方法。 In scala, compiler does the type inference and assign the most closest(or may be Restrictive) type for each variable or a method. 在scala中,编译器执行类型推断并为每个变量或方法分配最接近(或可能是限制)类型。 I am new to scala, and from many sample code/ libraries, I have noticed that in many places people are not explicitly providing the types for most of the time. 我是scala的新手,从许多示例代码/库中,我注意到在许多地方,人们大多数时间都没有明确地提供类型。 But, in most of the code I wrote, I was/still am explicitly providing the types. 但是,在我编写的大多数代码中,我/仍然明确提供类型。 For eg: 例如:

val someVal: String = "def"

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

The reason I started to write this especially for method return type is that, when I write a method itself, I know what it should return. 我开始写这个特别是方法返回类型的原因是,当我自己编写一个方法时,我知道它应该返回什么。 So If I explicitly provide the return type, I can find out if I am making any mistakes. 所以如果我明确提供了返回类型,我可以知道我是否犯了任何错误。 Also, I felt it is easier to understand what that method returns by reading the return type itself. 此外,我觉得通过阅读返回类型本身更容易理解该方法返回的内容。 Otherwise, I will have to check what the return type of the last statement. 否则,我将检查最后一个语句的返回类型。

So my questions/doubts are : 1. Does it take less compilation time since the compiler doesn't have to infer much? 所以我的疑问/疑问是:1。编译时间是否需要更少的编译时间,因为编译器不必推断太多? Or it doesn't matter much ? 或者它没关系多少? 2. What is the normal standard in the scala world? 2.斯卡拉世界的正常标准是什么?

From " Scala in Depth " chapter 4.5 : 来自“ Scala in Depth ”第4.5章

For a human reading a nontrivial method implementation, infering the return type can be troubling. 对于人类阅读非常重要的方法实现,推断返回类型可能会令人不安。 It's best to explicitly document and enforce return types in public APIs. 最好在公共API中明确记录和实施返回类型。

From " Programming in Scala " chapter 2 : 来自“ Scala编程 ”第2章

Sometimes the Scala compiler will require you to specify the result type of a function. 有时,Scala编译器会要求您指定函数的结果类型。 If the function is recursive, for example, you must explicitly specify the function's result type. 例如,如果函数是递归的,则必须显式指定函数的结果类型。

It is often a good idea to indicate function result types explicitly. 明确指出函数结果类型通常是个好主意。 Such type annotations can make the code easier to read, because the reader need not study the function body to figure out the inferred result type. 这种类型的注释可以使代码更容易阅读,因为读者不需要研究函数体来找出推断的结果类型。

From " Scala in Action " chapter 2.2.3 : 来自“ Scala in Action ”第2.2.3节

It's a good practice to specify the return type for the users of the library. 为库的用户指定返回类型是一种很好的做法。 If you think it's not clear from the function what its return type is, either try to improve the name or specify the return type. 如果您认为函数的返回类型不清楚,请尝试改进名称或指定返回类型。

From " Programming Scala " chapter 1 : 来自“ Programming Scala ”第1章

Recursive functions are one exception where the execution scope extends beyond the scope of the body, so the return type must be declared. 递归函数是执行范围超出正文范围的一个例外,因此必须声明返回类型。

For simple functions perhaps it's not that important to show it explicitly. 对于简单的函数,也许明确地显示它并不重要。 However, sometimes the inferred type won't be what's expected. 但是,有时推断类型不会是预期的类型。 Explicit return types provide useful documentation for the reader. 显式返回类型为读者提供了有用的文档。 I recommend adding return types, especially in public APIs. 我建议添加返回类型,尤其是在公共API中。

You have to provide explicit return types in the following cases : 在以下情况下,您必须提供显式返回类型

  • When you explicitly call return in a method. 在方法中显式调用return时。
  • When a method is recursive. 当一个方法是递归的。
  • When two or more methods are overloaded and one of them calls another; 当两个或多个方法重载并且其中一个方法调用另一个时; the calling method needs a return type annotation. 调用方法需要返回类型注释。
  • When the inferred return type would be more general than you intended, eg, Any. 当推断的返回类型比您预期的更通用时,例如,Any。

Another reason which has not yet been mentioned in the other answers is the following. 其他答案中尚未提及的另一个原因如下。 You probably know that it is a good idea to program to an interface, not an implementation . 您可能知道编程到接口是一个好主意,而不是实现

In the case of return values of functions or methods, that means that you don't want users of the function or method to know what specific implementation of some interface (or trait) the function returns - that's an implementation detail you want to hide. 对于函数或方法的返回值,这意味着您不希望函数或方法的用户知道函数返回的某个接口(或特征)的具体实现 - 这是您要隐藏的实现细节。

If you write a method like this: 如果你写一个像这样的方法:

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

def example() = new ExampleImpl1

then the return type of the method will be inferred to be ExampleImpl1 - so, it is exposing the fact that it is returning a specific implementation of trait Example . 那么该方法的返回类型将被推断为ExampleImpl1 - 因此,它暴露了它返回特征Example的特定Example的事实。 You can use an explicit return type to hide this: 您可以使用显式返回类型来隐藏它:

def example(): Example = new ExampleImpl1

The standard rule is to use explicit types for API (in order to specify the type precisely and as a guard against refactoring) and also for implicits (especially because implicits without an explicit type may be ignored if the definition site is after the use site). 标准规则是使用API​​的显式类型(为了精确指定类型并防止重构)以及implicits(特别是因为如果定义站点位于使用站点之后,可能会忽略没有显式类型的implicits) 。

To the first question, type inference can be a significant tax, but that is balanced against the ease of both writing and reading expressions. 对于第一个问题,类型推断可能是一个重要的税收,但这与写作和阅读表达的容易性相平衡。

In the example, the type on the local list is not even a "better java." 在示例中,本地列表上的类型甚至不是“更好的java”。 It's just visual clutter. 这只是视觉上的混乱。

However, it should be easy to read the inferred type. 但是,应该很容易阅读推断类型。 Occasionally, I have to fire up the IDE just to tell me what is inferred. 偶尔,我必须启动IDE只是为了告诉我推断的内容。

By implication, methods should be short enough so that it's easy to scan for the result type. 通过暗示,方法应该足够短,以便易于扫描结果类型。

Sorry for the lack of references. 很抱歉缺少参考资料。 Maybe someone else will step forward; 也许别人会挺身而出; the topic is frequent on MLs and SO. MLs和SO上经常出现这个话题。

2. The scala style guide says 斯卡拉风格指南

Use type inference where possible, but put clarity first, and favour explicitness in public APIs. 尽可能使用类型推断,但首先要明确,并在公共API中支持显式。

You should almost never annotate the type of a private field or a local variable, as their type will usually be immediately evident in their value: 您几乎不应该注释私有字段或局部变量的类型,因为它们的类型通常会在其值中立即显示:

private val name = "Daniel"

However, you may wish to still display the type where the assigned value has a complex or non-obvious form. 但是,您可能仍希望显示指定值具有复杂或非显而易见形式的类型。

All public methods should have explicit type annotations. 所有公共方法都应该有明确的类型注释。 Type inference may break encapsulation in these cases, because it depends on internal method and class details. 在这些情况下,类型推断可能会破坏封装,因为它取决于内部方法和类详细信息。 Without an explicit type, a change to the internals of a method or val could alter the public API of the class without warning, potentially breaking client code. 如果没有显式类型,对方法或val的内部的更改可能会在不发出警告的情况下更改类的公共API,从而可能破坏客户端代码。 Explicit type annotations can also help to improve compile times. 显式类型注释也可以帮助改善编译时间。

The twitter scala style guide says of method return types: twitter scala样式指南说明了方法返回类型:

While Scala allows these to be omitted, such annotations provide good documentation: this is especially important for public methods. 虽然Scala允许省略这些注释,但这样的注释提供了良好的文档:这对于公共方法尤其重要。 Where a method is not exposed and its return type obvious, omit them. 如果方法未公开且返回类型明显,则省略它们。

I think there's a broad consensus that explicit types should be used for public APIs, and shouldn't be used for most local variable declarations. 我认为有一个广泛的共识,即显式类型应该用于公共API,不应该用于大多数局部变量声明。 When to use explicit types for "internal" methods is less clear-cut and more a matter of judgement; 何时使用“内部”方法的显式类型不太明确,更多的是判断问题; different organizations have different standards. 不同的组织有不同的标准。

1. Type inference doesn't seem to visibly affect compilation time for the line where the inference happens (aside from a few rare cases with implicits which are basically compiler bugs) - after all, the compiler still has to check the type, which is pretty much the same calculation it would use to infer it. 1.类型推断似乎不会明显影响推理发生的行的编译时间(除了一些基本上是编译器错误的隐含的罕见情况) - 毕竟,编译器仍然需要检查类型,这是用来推断它的计算几乎相同。 But if a method return type is inferred then anything using that method has to be recompiled when that method changes. 但是,如果推断出方法返回类型,则在该方法更改时必须重新编译使用该方法的任何内容。

So inferring a method (or public variable) that's used in many places can slow down compilation (particularly if you're using incremental compilation). 因此推断在许多地方使用的方法(或公共变量)会降低编译速度(特别是如果您使用增量编译)。 But inferring local or private variables, private methods, or public methods that are only used in one or two places, makes no (significant) difference. 但推断仅在一个或两个地方使用的本地或私人变量,私有方法或公共方法,没有(显着)差异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM