8
object A extends App {

def closure1(x:Int) = {
  object O {
   def getX = x
   def add(y:Int) = x+y
  }
  val foo = O
  foo
}

def closure2(x:Int) {
  object O {
   def getX = x
   def add(y:Int) = x+y
  }
  val foo = O
  foo
}

println(closure1(4).getClass)
println(closure2(4).getClass)
}

result:
 $scala A
 class A$O$3$
 void
  1. 为什么返回类型不同?
  2. 我真的不在乎返回类型。我想调用 getX 并添加 - 我想做像closure1(4).getX 这样的事情 - 这是非法的。我怎么做 ?
4

2 回答 2

17

Scala 有一个不返回任何有趣值的代码的简写符号:省略=符号。在 Java 中,这将返回void,即什么都没有;但在 Scala 中,它实际上是.()类型的唯一成员Unit。无论哪种方式,它都是一样的:什么都没有或一个无意义的占位符。

您想要一个无意义的占位符的原因是,当您编写通用代码时,您宁愿不必处理某些情况与没有什么不同的情况。

反正:

def f(): Unit = println("Hi")

是一个仅显式返回无内容()值的函数(这也是println返回的值)。速记是

def f() { println("Hi") }

现在有一个偷偷摸摸的补充,那就是在 Scala 中,与许多 C 派生语言一样,您可以从所做的任何事情中丢弃返回值。而当你扔掉它时,剩下的就是(). Scala 会警告你closure2你正在做一些可疑的事情:

<console>:16: warning: a pure expression does nothing in statement position
you may be omitting necessary parentheses
         foo
         ^
defined module A

但仍然会让你这样做(因为历史上预计这会起作用)。

所以,总结一下:

def f {}

是一种仅返回无内容占位符的方法()。如果您将其完整地写出来,则语法将是

def f: Unit = {}

当您尝试返回错误类型的值时,它不会抱怨它会丢弃该值并为您提供 type Unit,但通常会发出警告:

def f: Unit = 5
def f { 5 }

(请注意,这些天大多数人反对简写形式(这些天是 2.10-is-stable),这在很大程度上是因为在没有明确解释差异的情况下,新用户经常=在没有意识到的情况下忽略它,然后想知道为什么会这样不工作。所以在未来(2.11 或 2.12 弃用?)该def f {}表格可能不起作用。)

如果你真的想要一个返回值——例如,因为你想返回你的对象O(顺便说一下,你可以直接这样做而无需先将其分配给foo),请确保包括=

def f = { object O { def g = 5 }; O }

scala> f.g
res0: Int = 5

(提示:编译器会抱怨你在这里使用了结构类型。你最好使用trait HasG { def g: Int }and then object O extends HasG;否则 Scala 实际上使用反射来调用f.g一些我从未完全能够理解的基本原理。)

于 2013-08-21T22:03:44.793 回答
1

我认为 Rex 已经解释了原因,您省略了=when define closure2,这使 Scala 编译器认为您不想返回任何内容,即使您打算返回foo

scala> def closure3(x: Int) {
     |   object O {
     |     def getX = x
     |     def add(y: Int) = x + y
     |   }
     |   val foo = O
     |   foo
     | }
<console>:17: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
         foo
         ^
closure3: (x: Int)Unit

注意返回类型closure3Unit

scala> def closure4(x: Int) = {
     |   object O {
     |     def getX = x
     |     def add(y: Int) = x + y
     |   }
     |   O
     | }
closure4: (x: Int)Object{def getX: Int; def add(y: Int): Int}

scala> closure3(2)

closure3(2)什么都不返回,所以你不能打电话getX

scala> closure4(2)
res10: Object{def getX: Int; def add(y: Int): Int} = O$2$@a4920bc
于 2013-08-21T23:52:00.783 回答