【问题标题】:Strange behaviour when importing types in Scala 2.10在 Scala 2.10 中导入类型时的奇怪行为
【发布时间】:2013-02-06 18:44:19
【问题描述】:

今天我清除了我的 .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.rest 内的任何位置访问包 com.abc 中的类(即使使用完整路径),编译器也会抱怨找不到该类型。

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

我很想知道我可能做错了什么,或者我可以如何解决这个问题。

更新:

先导入父类,再定义当前包,问题就解决了:

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

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

所以这行得通,但我仍然很想知道为什么反过来工作,然后停止工作,以及我到底该如何解决它。我仔细看了看,在父包内的任何地方都找不到以 com 为名的包、对象或特征。

与工作表相关的更新:

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

我有这么多工作表,我什至没有试图找出问题出在哪里。我只是将它们全部移到了自己的包中,就像魔术一样,问题就消失了。

因此,今天的经验教训是:如果您在工作表内创建内容,则可以从工作表外看到。

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

想想sbt clean 和清理后的 ivy 缓存如何设法突出之前隐藏的问题仍然很有趣,但是嘿,那是另一个故事......

【问题讨论】:

  • 你能检查一下你没有在包com.abc.rest.com中定义任何类/特征/对象吗?一旦包com.abc.rest.com 存在,并且假设您在包com.abc.rest 中,com 将指定com.abc.rest.com 而不是_root_.com。最快的检查方法是在“com/abc/rest/com”子文件夹中查找任何 .class 文件,甚至无需扫描源文件。
  • 这很有趣,谢谢。我现在看了看,但找不到类似的东西。
  • 好吧,这很奇怪。不过看起来真的很像。例如,如果您的任何文件具有重复的包定义(如同一文件中的package com.abc.rest; package com.abc.rest; ...),您将获得此行为。也许你有这个重复的包子句在同一个文件中你得到错误的地方(这可以解释为什么你看不到 .class 文件有任何可疑之处,因为编译文件失败会防止为文件内的 any 类定义生成 .class 文件)。
  • @RégisJean-Gilles 事实证明你是对的,唯一的问题是错误的包或人工制品名称在工作表中。我从来没有意识到它们在工作表之外是可见的,并且由于某种原因,直到我清理了我的输出文件才突出显示。请把你的 cmets 记下来作为答案,以便我接受。
  • 我看到您已经提出了自己的答案。只需接受它(也许编辑以添加对我提到的包问题的快速参考)。

标签: scala compiler-construction sbt scala-2.10


【解决方案1】:

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

如果您在包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 工作表没有沙盒化时,您在工作表中定义的内容会影响您的项目代码(而不仅仅是让项目代码影响工作表)。因此,在工作表中重复的包子句很可能会导致您遇到的错误。

【讨论】:

    【解决方案2】:

    如果包名冲突,可能会有一个自定义错误消息。从__root__ 开始,查看指定完整路径是否可以解决问题。前任。 import __root__.com.foo.bar._

    【讨论】:

      猜你喜欢
      • 2021-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      相关资源
      最近更新 更多