JVM语言的包

rwa*_*ace 2 java jvm scala clojure jvm-languages

在Java中,类被放置在一个包中包含的声明package com.acme.foo ,并把你的源文件中像一个子目录com/acme/foo.

我正在研究一种JVM语言,它不会像Java 那样重复自己的风格,所以我将使用这些机制中的一种或另一种,但不是两种,我想知道使用哪种机制.

其他JVM语言如Scala和Clojure如何处理它?他们需要两种机制还是只需一种机制,如果是这样的话?

Sus*_*ter 11

正如Travis Brown对问题的评论中提到的那样,scalac没有对源文件的路径或名称进行任何此类约束或限制,如果您愿意,甚至可以在一个文件中指定多个包.

但是,scalac生成的字节码会将字节码类文件放入相应类加载器所需的必要目录结构中.

以下是一些显示灵活性的示例(我不一定提倡这些样式,只是展示了灵活性).

// in packages1.scala file in local directory
package my {
  package states {
    sealed trait State
    case class CheckingOut(shoppingCartId: Long) extends State
    case class ConfirmedOrder(orderId: Long) extends State
    case class ItemShipped(orderId: Long, itemId: Long, quantity: Int) extends State
  }
}
Run Code Online (Sandbox Code Playgroud)

还有这个...

// in packages2.scala file
package com.foo.bar

sealed trait Scale
case object WebScale extends Scale
case object LolScale extends Scale
case object RoflScale extends Scale
case object WatScale extends Scale
Run Code Online (Sandbox Code Playgroud)

这种风格也是可能的:

// in packages3.scala file
package foo {
  package awesomeness {
    class Main extends App {
      println("Bananas are awesome")
    }
  }
}

package foo {
  package lameness {
    class Main extends App {
      println("Congress is pretty lame, honestly")
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

除此之外...

package foo
package bar

// now we are in package foo.bar for remainder of file unless another package statement is made
Run Code Online (Sandbox Code Playgroud)

这是生成的源和编译的字节码树:

$ tree
.
??? com
?   ??? foo
?       ??? bar
?           ??? LolScale$.class
?           ??? LolScale.class
?           ??? RoflScale$.class
?           ??? RoflScale.class
?           ??? Scale.class
?           ??? WatScale$.class
?           ??? WatScale.class
?           ??? WebScale$.class
?           ??? WebScale.class
??? foo
?   ??? awesomeness
?   ?   ??? Main$delayedInit$body.class
?   ?   ??? Main.class
?   ??? lameness
?       ??? Main$delayedInit$body.class
?       ??? Main.class
??? my
?   ??? states
?       ??? CheckingOut$.class
?       ??? CheckingOut.class
?       ??? State.class
??? packages1.scala
??? packages2.scala
??? packages3.scala

8 directories, 19 files
Run Code Online (Sandbox Code Playgroud)

我不确定Clojure是否支持这种灵活性,但Clojure约定是使用结构化源代码的Java约定及其常用的构建工具lein(请参阅此处的leiningen教程).

有一两件事要注意,然而,就是在这两个Scala和Clojure的存在似乎是从出发$DOMAIN.$APPLICATION,往往是在Java世界中(如使用的格式com.oracle.jdbc...,org.hibernate.session...等等).Scala里,你会看到包名的$域部分被取出完全(例如scalaz...,akka.{actor,io, ...}等).

另外值得注意的是您可以从Scala中导入包的方式:

  • 导入foo.bar包中的所有公共"东西" :import foo.bar._
  • 只导入一个类/特征/ etc(就像Java一样): import foo.bar.Baz
  • 从包中导入一个类/ trait/etc并在当前范围内重命名: import foo.bar.{Baz => FooBarBaz}
  • 从包中导入一部分内容: import foo.bar.{Baz, Boo, Bla}

另外值得注意的是Scala中的包私有作用域:

package foo.bar

class Baz{
  private[bar] def boo[A](a: A)
  private[foo] def bla[A](a: A)
}
Run Code Online (Sandbox Code Playgroud)

上面boofoo.bar包(和子包)bla的私有,foo并且是私有的以及它的所有子包.

有关更多详细信息,请阅读Scala语言规范和相关链接: