[英]Packages in JVM languages
在Java中,類被放置在一個包中包含的聲明package com.acme.foo
並把你的源文件中像一個子目錄com/acme/foo
。
我正在研究一種JVM語言,它不會像Java 那樣重復自己的風格,所以我將使用這些機制中的一種或另一種,但不是兩種,我想知道使用哪種機制。
其他JVM語言如Scala和Clojure如何處理它? 他們需要兩種機制還是只需一種機制,如果是這樣的話?
正如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
}
}
和這個...
// 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
這種風格也是可能的:
// 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")
}
}
}
除此之外...
package foo
package bar
// now we are in package foo.bar for remainder of file unless another package statement is made
這是生成的源和編譯的字節碼樹:
$ 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
我不確定Clojure是否支持這種靈活性,但Clojure約定是使用Java常規來構造源代碼,使用它常用的構建工具lein
(請參閱leiningen教程 )。
然而,需要注意的一點是,在Scala和Clojure中,似乎與$DOMAIN.$APPLICATION
格式不同,它通常在Java世界中使用(例如com.oracle.jdbc...
, org.hibernate.session...
等)。 在Scala中,您將看到包名稱的$ DOMAIN部分被完全取出(例如scalaz...
, akka.{actor,io, ...}
等)。
另外值得注意的是您可以從Scala中的包導入方式:
foo.bar
包中的所有公共“東西”: import foo.bar._
import foo.bar.Baz
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)
}
上面的boo
是foo.bar
包(和子包)的私有,而bla
是foo
及其所有子包的私有。
有關更多詳細信息,請閱讀Scala語言規范和相關鏈接:
Clojure有點像Java,但是沒有真正的類,所以它有點不同。
如果有一個命名空間project.foo,那么Clojure編譯器將期望在名為foo.clj的文件中的源根目錄下的項目目錄中找到它。
例如,假設src是保存源文件的目錄。 然后project.foo命名空間將在src/project/foo.clj
,並在頂部添加類似聲明(ns project.foo)
。
我認為很難擺脫這一點,因為在運行時,當Clojure加載文件時(大多數Clojure被捆綁為源代碼),Clojure運行時會將文件作為資源加載,這需要它在右邊放在目錄層次結構中(無論是基於jar還是基於文件)。
就個人而言,我也不介意包名==目錄位置約定。 它使工具可以輕松地在編譯或運行時查找文件,如果我只是使用emacs,也可以讓我輕松找到它們。 它也感覺有點組織,然后只是一個目錄中的一堆文件,雖然這可能更多的是我一直在使用它后的習慣。
我對Clojure沒有任何經驗,但我確實對Scala有一些經驗,scala也使用子目錄作為他們的包,但其中一個漂亮的功能是重命名類似於C ++ typedef關鍵字功能的類。 一個有趣的想法是,如果你創建了一個類似於C ++的鏈接器,並允許一個typedef功能但仍然保留在JVM中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.