我有一个应该返回Int的方法.我试图理解为什么Eclipse不会让我编译它,即使我在if语句中看起来我确实正在返回一个Int.有什么我错过的非常明显吗?在继续编写更多代码之前,我试图理解Scala的这个方面.
这是方法:
def contains1(sfType: TokenType): Int = {
if (Tokens.KEYWORDS.contains(sfType)) {
val retVal = TokenTypes.RESERVED_WORD
}
}
Run Code Online (Sandbox Code Playgroud)
Eclipse在第2行抱怨---'类型不匹配; 发现:所需单位:Int"
TokenTypes is - public abstract interface org.fife.ui.rsyntaxtextarea.TokenTypes and RESERVED_WORD is - public static final int RESERVED_WORD = 6;
Run Code Online (Sandbox Code Playgroud)
我在这里读过这篇文章:发现:需要单位:Int - 如何纠正这个?并试图在发布之前解决问题,但我仍然不知所措.
编辑:该方法应该返回一个Int,我错误地输入了返回类型.我的问题仍然存在.Eclipse仍然抱怨.
Dan*_*ral 72
我将首先解释什么类型Unit,以防万一.即使你已经知道,其他有同样问题的人可能也不会知道.
类型Unit类似于C或Java中已知的类型void.在那些语言中,这意味着"这不会返回任何东西".但是,Scala中的每个方法都返回一个值.
为了弥合每个返回某些东西的方法之间的差距,并且没有任何有用的东西可以返回,那就是Unit.此类型是一个AnyVal,这意味着它不会在堆上分配,除非它被装箱或是对象上的字段类型.此外,它只有一个值,其字面值().也就是说,你可以这样写:
val x: Unit = ()
Run Code Online (Sandbox Code Playgroud)
这样做的实际效果是,当一个方法"返回"时Unit,编译器不必实际返回任何值,因为它已经知道该值是什么.因此,它可以Unit通过在字节码级别上声明它们来实现返回的方法void.
无论如何,如果你不想退货,你会回来Unit.
现在让我们看看给出的代码.Eclipse说它返回了Unit,事实上,Eclipse是正确的.然而,大多数人实际上使误差具有方法返回的AnyVal或Any,不是Unit.有关示例,请参阅以下代码段:
scala> if (true) 2
res0: AnyVal = 2
Run Code Online (Sandbox Code Playgroud)
所以发生了什么事?好吧,当Scala找到一个if语句时,它必须弄清楚它返回的类型是什么(在Scala中,if语句也返回值).考虑以下假设线:
if (flag) x else y
Run Code Online (Sandbox Code Playgroud)
显然,返回值将是任一x或y,所以类型必须是使得两个x和y将适合.一种这样的类型是Any,因为一切都有类型Any.如果两个x和y是同一类型的-说Int-那么这也将是一个有效的返回类型.由于斯卡拉挑选最具体的类型,这将挑选Int过Any.
现在,当你发生了什么不具备的else声明?即使没有else陈述,情况也可能是假的 - 否则,使用就没有意义了if.在这种情况下,Scala所做的是添加一个else语句.也就是说,它重写了这样的if语句:
if (true) 2 else ()
Run Code Online (Sandbox Code Playgroud)
就像我之前说过的那样:如果你没有任何回报,请回来Unit!这正是发生的事情.由于这两个Int和Unit的AnyVal,而且考虑到AnyVal是不是更具体的Any,该行返回AnyVal.
到目前为止,我已经解释了其他人可能看到的内容,但没有解释问题中特定代码中发生的情况:
if (Tokens.KEYWORDS.contains(sfType)) {
val retVal = TokenTypes.RESERVED_WORD
}
Run Code Online (Sandbox Code Playgroud)
我们已经看到Scala会像这样重写它:
if (Tokens.KEYWORDS.contains(sfType)) {
val retVal = TokenTypes.RESERVED_WORD
} else ()
Run Code Online (Sandbox Code Playgroud)
我们还看到Scala将在两个可能的结果之间选择最具体的类型.最后,Eclipse告诉使用返回类型Unit,所以唯一可能的解释是这个类型:
val retVal = TokenTypes.RESERVED_WORD
Run Code Online (Sandbox Code Playgroud)
也是Unit.这恰恰是正确的:在Scala中声明事物的语句具有类型Unit.顺便说一下,做任务.
正如其他人所指出的那样,解决方案是删除赋值并添加一个else语句,同时返回Int:
def contains1(sfType: TokenType): Int =
if (Tokens.KEYWORDS.contains(sfType)) TokenTypes.RESERVED_WORD
else -1
Run Code Online (Sandbox Code Playgroud)
(注意:我已经重新格式化了方法,以遵循Scala程序员中更常见的编码风格)
我有一种感觉,你需要改变你的方法看起来像下面之一
def contains1(sfType: TokeType): Int = {
if (Tokens.KEYWORDS.contains(sfType))
TokenTypes.RESERVED_WORD
else
-1
}
def contains1(sfType: TokenType) = if (Tokens.KEYWORDS.contains(sfType)) TokenTypes.RESERVED_WORD else -1
Run Code Online (Sandbox Code Playgroud)
在scala中没有单一的if陈述
由于当评价必须返回一个值的每个表达式(它可以是一个空值的类型,Unit),则if表达式必须总是以匹配else分支,都必须返回相同的类型,或者在最坏的情况下阶将推断的最常见超类型.
在您的代码中,您Int从if分支返回a ,但else缺少分支.
正如其他答案所述:
单个if表达式返回其中唯一的替代方法,对于原始帖子,它是赋值的返回值(),类型为Unit