在Scala 2.10中导入类型时出现奇怪的行为

时间:2013-02-06 18:44:19

标签: scala compiler-construction sbt scala-2.10

今天我清除了我的.ivy缓存并清理了我的项目输出目标。从那时起,我在使用SBT运行测试或在Scala IDE中进行编辑时遇到了非常奇怪的行为。

鉴于以下内容:

package com.abc.rest

import com.abc.utility.IdTLabel

我会收到以下错误:

object utility is not a member of package com.abc.rest.com.abc

请注意,com.abc重复两次,因此看起来编译器在执行导入时会使用当前包的上下文(也许它应该这样做,但我以前从未注意过它。)

另外,如果我尝试从com.abc内的任何地方访问包com.abc.rest中的类(即使使用完整路径),编译器也会抱怨找不到类型。

似乎只有在我尝试包含来自父包的文件时才会出现错误。我觉得奇怪的是我的代码曾经工作过。它只是在我清理了我的项目和常春藤缓存之后才开始发生,所以编译器的后续版本可能比前一版本更严格。

我会喜欢我可能做错的一些想法,或者我如何解决这个问题。

更新

首先导入父类然后定义当前包,问题就消失了:

import com.abc.utility.IdTLabel
import com.abs._

package com.abc.rest {
 // Define classes belonging to com.abc.rest here
}

所以这有效,但我仍然想知道为什么在地球上另一种方式工作,然后停止工作,以及我怎么能解决它。我看起来很好看,并且在父包内的任何地方都没有找到com名称的包,对象或特征。

与工作表相关的更新:

属于同一个软件包的Scala工作表共享相同的范围,听起来很明显,但事实并非如此。工作表不是沙盒 - 他们可以看到项目,,项目可以看到它们。因此,您在工作表文件中创建的所有“测试”对象,特征和类也将在项目的其余部分中显示。

我有很多工作表,我甚至没有尝试查看问题出在哪里。我只是将它们全部移到自己的包中,就像魔法一样,问题就消失了。

所以,当天学到的经验教训: 如果您在工作表中创建内容,则可以从工作表外部看到。

无论如何,这个新发现的知识会派上用场,这意味着任何“有趣的”都可以在工作表中构建,监控和调整,而项目的其余部分实际上可以使用它。实际上非常酷。

考虑如何sbt clean清理常春藤缓存以突出之前隐藏的问题仍然很有趣,但是嘿,这是另一个故事....

2 个答案:

答案 0 :(得分:3)

(应JacobusR的要求,我正在从我之前的评论中做出正确答案)。

如果您在包com.abc.rest.com中定义了一些类/特征/对象,则会发生这种情况。一旦包com.abc.rest.com存在,并且假设您在包com.abc.rest中,com将指定com.abc.rest.com而不是_root_.com。在没有扫描源文件的情况下,检查最快(但非结论性)的方法是在“com / abc / rest / com”子文件夹中查找任何.class文件。

特别是如果您的任何文件具有重复的包定义(如包com.abc.rest; package com.abc.rest; ...中),则会出现此行为。如果你在同一个文件中的某个地方有这个重复的包子句,你会得到错误,你甚至看不到任何与.class文件有关的东西,因为编译文件失败会阻止为任何类生成.class文件文件内的定义。

有用信息的最后一点是,当你发现scala工作表没有沙箱时,你在工作表中定义的内容会影响你的项目代码(而不是只让项目的代码影响工作表)。因此,工作表中的重复包子句很可能导致您得到的错误。

答案 1 :(得分:1)

如果包名称冲突,则可能存在自定义错误消息。查看指定完整路径是否从__root__开始解决问题。防爆。 import __root__.com.foo.bar._