使用Unit
或()
从方法中显式返回Unit
类型的正确方法是什么?在我看来,这两种方法在我尝试过的所有情况下都有效。
对于上下文,如果我正在编写一个具有副作用的方法并返回调用另一个方法的Unit
,则该情况经常发生,该方法也执行副作用,但是返回一些值而不是Unit
。例如
def effectAndReturn(): String = {
val msg = "Hello, SO"
println(msg)
msg
}
def doEffect(): Unit = {
val _ = effectAndReturn()
() // `Unit` also works here
}
据我了解,()
是存在的唯一类型Unit
的值。返回Unit
中的令牌doEffect()
引用的是Unit
伴随对象;我很困惑如何返回一个值,因为甚至没有定义任何apply
方法。据我所知,返回给定抽象类类型的伴随对象作为返回值无效。
将它们放入Scala REPL中也很有趣
scala> val parenUnit = ()
parenUnit: Unit = ()
scala> parenUnit
// Returns blank line
scala> val wordUnit = Unit
wordUnit: Unit.type = object scala.Unit
scala> wordUnit
res1: Unit.type = object scala.Unit
scala> res1
res2: Unit.type = object scala.Unit
()
只是一个Unit
值,而Unit
会返回一个类型,这对我来说没有意义,因为据我所知,没有其他伴随对象会这样做。我的猜测是,与任何其他类型相比,编译器都以特定且独特的方式处理Unit
,但究竟如何呢?
答案 0 :(得分:6)
所以,我们有:
Unit
类型 ()
,类型为Unit
Unit
伴随对象,引起混乱。它是类型Unit
的不是。它的类型为Unit.type
(它自己的单例类型)。但是... Scala会自动将所有内容隐式转换为Unit
,这就是为什么可以在需要Unit
类型的地方使用它的原因。 TLDR:使用()
答案 1 :(得分:1)
假设在名为TestUnit
的类中有两个方法:
class TestUnit {
def foo(): Unit = 2217
def bar(): Int = 1478
}
让我们看看它的字节码:
// access flags 0x1
public foo()V
L0
LINENUMBER 4 L0
SIPUSH 2217
POP
RETURN // returns void
L1
LOCALVARIABLE this Lunit/TestUnit; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public bar()I
L0
LINENUMBER 5 L0
SIPUSH 1478
IRETURN // returns integer because it is declared in method
L1
LOCALVARIABLE this Lunit/TestUnit; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
我的假设是-Scala编译器仅在将RETURN
声明为返回类型的每个方法中放置Unit
指令(返回void)。 (您可以查看列表here)
因此,您可以返回doEffect()
中的任何类型。但是正如 @ghik 所说,最好使用()
。