Scala编译器通常可以推断方法的返回类型,但在某些情况下需要指定返回类型。例如,递归方法需要指定返回类型。什么时候Scala中的方法需要返回类型?
我注意到有时候我得到了“重载的方法(methodname)需要返回类型”的错误消息,但是这不是一般规则,必须总是为重载方法指定返回类型(我有我没有得到的例子这个错误)。
什么时候需要指定返回类型,对于一般的方法以及特定的重载方法?
Scala编译器通常可以推断方法的返回类型,但在某些情况下需要指定返回类型。例如,递归方法需要指定返回类型。什么时候Scala中的方法需要返回类型?
我注意到有时候我得到了“重载的方法(methodname)需要返回类型”的错误消息,但是这不是一般规则,必须总是为重载方法指定返回类型(我有我没有得到的例子这个错误)。
什么时候需要指定返回类型,对于一般的方法以及特定的重载方法?
的Programming Scala本书的Chapter 2. Type Less, Do More提到:
时,显式类型注解是必需的。
在实际应用中,你必须为下列情况提供明确的类型注释:在下列情况下
方法的返回值:
- 当你明确地调用一个方法的返回(甚至在结束)。
- 当一个方法是递归的。
- 当一个方法被重载并且其中一个方法调用另一个时。调用方法需要返回类型注释。
- 当推断的返回类型比您想要的更通用时,例如
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()
}
重载方法有时需要明确的返回类型。当一个这样的方法调用另一个方法时,我们必须向执行调用的方法添加一个返回类型,如本例中所示。
// 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")))
两个
joiner
方法连接字符串的List
在一起。
第一种方法也为分隔符字符串提供参数。
第二种方法使用单个空间的“默认”分隔符调用第一个方法。如果您运行此脚本,会出现以下错误。
... 9: error: overloaded method joiner needs result type
def joiner(strings: List[String]) = joiner(strings, "")
由于第二
joiner
方法调用第一,它需要显式String
返回类型。它应该是这样的:
def joiner(strings: List[String]): String = joiner(strings, " ")
基本上,指定的返回类型可以是即使斯卡拉可以推断出它一个很好的做法。
由于(我个人的)风格问题,我给明确的返回类型为所有,但最简单的方法(基本上,一个俏皮话,没有条件逻辑)。
请记住,如果您让编译器推断方法的结果类型,它可能会比您想要的更具体。 (例如,HashMap中,而不是地图。)
而且因为你可能要暴露在你的返回类型的最小接口(见例如这个SO question),这种推断可能的方式获得。
约在最后一个场景(“当推断返回类型会更普遍比你预期”),Ken Bloom补充说:
当你希望编译器来验证指定的返回类型在函数的代码返回类型,你预计
(该错误代码触发“比预期的返回类型更普遍的是:
// 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 [任何]因为返回一个空的列表,但肯叫出来:
List(0)
不与0元素创建列表。
它创建一个包含一个元素(值为0)的List[Int]
。
因此,一个条件分支上的List[Int]
和另一个条件分支上的List[String]
概括为List[Any]
。
在这种情况下,typer不是过于普通 - 这是代码中的错误。
)
“当推断的返回类型比您想要的更通用时,例如Any。”这很奇怪。其实,我会考虑Typer的一个bug。我从来没有经历过这样的事情。你有一个例子吗? – soc 2010-06-27 15:22:08
@soc:http://programming-scala.labs.oreilly.com/ch02。html确实有一个例子,除非你指定了返回类型,否则返回一个List(0)(大小为0的List)将会返回,而List [Any]而不是List [String]。 – VonC 2010-06-27 15:38:29
'List(0)'不会创建包含0个元素的列表。它创建一个包含一个元素(值为“0”)的List [Int]。因此,一个条件分支上的'List [Int]'和另一个条件分支上的'List [String]'概括为'List [Any]'。在这种情况下,typer不是过于普通 - 这是代码中的一个错误。其中添加了另一个规定返回类型的规则:**当您希望编译器验证函数中的代码返回您期望的类型时,指定返回类型。** – 2010-06-27 16:13:51
作为(我个人的)风格问题,我给明确的返回类型为所有,但最简单的方法(基本上,一个俏皮话,没有条件逻辑)。请记住,如果让编译器推断方法的结果类型,它可能会比你想要的更具体。 (例如,'HashMap'而不是'Map'。) – 2010-06-27 14:36:27
@Randall是的,好点(关于返回类型太具体)。 – Jesper 2010-06-27 20:49:55