scala - Scala 中的方法何时需要返回类型?

标签 scala methods overloading scala-2.8

Scala 编译器通常可以推断方法的返回类型,但在某些情况下需要指定返回类型。例如,递归方法需要指定返回类型。

我注意到有时我会收到错误消息“重载的方法(方法名)需要返回类型”,但这并不是一个一般规则,即必须始终为重载方法指定返回类型(我有一些我没有收到此错误的示例)。

什么时候需要指定返回类型,对于一般的方法,特别是对于重载的方法?

最佳答案

Chapter 2. Type Less, Do More Programming Scala 书中提到:

When Explicit Type Annotations Are Required.

In practical terms, you have to provide explicit type annotations for the following situations:

Method return values in the following cases:

  • When you explicitly call return in a method (even at the end).
  • When a method is recursive.
  • When a method is overloaded and one of the methods calls another. The calling method needs a return type annotation.
  • When the inferred return type would be more general than you intended, e.g., Any.


例子:
// code-examples/TypeLessDoMore/method-nested-return-script.scala
// ERROR: Won't compile until you put a String return type on upCase.

def upCase(s: String) = {
  if (s.length == 0)
    return s    // ERROR - forces return type of upCase to be declared.
  else
    s.toUpperCase()
}

Overloaded methods can sometimes require an explicit return type. When one such method calls another, we have to add a return type to the one doing the calling, as in this example.


// code-examples/TypeLessDoMore/method-overloaded-return-script.scala
// Version 1 of "StringUtil" (with a compilation error).
// ERROR: Won't compile: needs a String return type on the second "joiner".

object StringUtil {
  def joiner(strings: List[String], separator: String): String =
    strings.mkString(separator)

  def joiner(strings: List[String]) = joiner(strings, " ")   // ERROR
}
import StringUtil._  // Import the joiner methods.

println( joiner(List("Programming", "Scala")) )

The two joiner methods concatenate a List of strings together.
The first method also takes an argument for the separator string.
The second method calls the first with a “default” separator of a single space.

If you run this script, you get the following error.


... 9: error: overloaded method joiner needs result type
def joiner(strings: List[String]) = joiner(strings, "")

Since the second joiner method calls the first, it requires an explicit String return type. It should look like this:


def joiner(strings: List[String]): String = joiner(strings, " ")

基本上,指定返回类型可能是一个好习惯,即使 Scala 可以推断它 .

Randall Schulz评论:

As a matter of (my personal) style, I give explicit return types for all but the most simple methods (basically, one-liners with no conditional logic).

Keep in mind that if you let the compiler infer a method's result type, it may well be more specific than you want. (E.g., HashMap instead of Map.)



而且由于您可能希望在返回类型中公开最小接口(interface)(例如,参见 SO question ),这种推断可能会妨碍您。

关于最后一种情况(“当推断的返回类型比您预期的更一般时”),Ken Bloom补充说:

specify the return type when you want the compiler to verify that code in the function returns the type you expected



(触发“比预期更一般的返回类型”的错误代码是:
// code-examples/TypeLessDoMore/method-broad-inference-return-script.scala
// ERROR: Won't compile. Method actually returns List[Any], which is too "broad".

def makeList(strings: String*) = {
  if (strings.length == 0)
    List(0)  // #1
  else
    strings.toList
}

val list: List[String] = makeList()  // ERROR

,我错误地解释和 List[Any] 因为返回一个空列表,但肯把它叫出来:

List(0) doesn't create a list with 0 elements.
It creates a List[Int] containing one element (the value 0).
Thus a List[Int] on one conditional branch and a List[String] on the other conditional branch generalize to List[Any].
In this case, the typer isn't being overly-general -- it's a bug in the code.
)

关于scala - Scala 中的方法何时需要返回类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3127208/

相关文章:

vb.net - VB.Net 中是否需要 'Overloads' 关键字?

java - 确定重载方法的输入

scala - 阅读比 CPU 核心数更多的 Kafka 主题

scala - 当定义闭包时,Scala 如何维护变量的值?

javascript初始化对象属性

python - 多态性——在覆盖现有方法的同时添加它们

java - java中有些私有(private)内部类可以不继承吗?

c - C 中函数重载的预编译选项

scala - 具有上限的函数中类型推断的奇怪行为

scala - `A >: Null` 的含义?