什么是Scala 2.8中的嵌套/未嵌套包?

时间:2010-05-13 20:55:38

标签: scala package scala-2.8

在Scala 2.7中,我可以写:

package com.acme.bar

class Bar

package com.acme.foo

class Foo {
  new bar.Bar
}

这不能在Scala 2.8中编译 - 但是这样做:

package com.acme 
package bar

class Bar

package com.acme
package foo

class Foo {
  new bar.Bar
}
  1. 这是什么动机?
  2. 关于范围和可见度的确切含义是什么?
  3. 我应该何时使用一种形式而不是另一种形式?

3 个答案:

答案 0 :(得分:18)

关于这一点,在邮件列表上进行了几次长时间的讨论。 请参阅this thread for the problemthis thread for the solution

至于含义,只有

package A
package B

表单将为A打开一个范围,这使得A的成员可以看不到前缀。如果您的项目包含多个相互引用的子包,则通常使用此表单。另一方面,您使用表格

package A.B.C

如果要将C集成到包层次结构中,并且不打算直接访问AB的其他成员。一个典型的案例是

package net.myorg.myproject

在这里,你不希望比其他人定义的那种容易受到攻击 net.java包会影响根级别java。在Scala 2.7中,您可以使用_root_导入来阻止这种情况。但这很难看,为了安全起见,你几乎无处不在。所以目前的解决方案要好得多,IMO。

答案 1 :(得分:13)

感谢目前为止的答案!让我添加两个小点,我们就完成了!

可见性

嵌套和未嵌套包之间的区别仅适用于范围。 可见性始终基于嵌套包。

package A

private[A] trait Secret

这有效:

package A
package B

trait AB extends Secret

这样做:

package A.B

trait AB extends A.Secret

在这两种情况下,结构都被解释为:

package A {
  trait Secret
  package B {
     //...
  }
}

作用域

将此与范围进行比较,您可以在其中想象对未使用的包进行此解释:

package A {
  private [A] trait Secret
}

package `A.B` {
   trait AB extends A.Secret

}

混合搭配

您可以随意混合和匹配嵌套和未嵌套的包:

package com.acme.project
package util.shazam
package blerg

答案 2 :(得分:9)

它不能让您更好地控制导入的内容吗?例如,如果有包:

package com.acme.foo.client
package com.acme.client

然后从Foo开始,对于client被引用的问题,是不是存在令人烦恼的含糊之处?例如,如果您想在Foo内执行通配符导入:

class Foo {
  import client._ //what is being imported?
}

如果代替client我们有一个包com.acme.java,那么这可能会更成问题:

class Foo {
    val jul = new java.util.LinkedList //compile error; cannot find util
}