[英]Scala application structure
我現在正在學習Scala,我想寫一些愚蠢的小應用程序,如控制台Twitter客戶端,或其他什么。 問題是,如何在磁盤上和邏輯上構建應用程序。 我知道python,在那里我只是創建一些帶有類的文件然后在主模塊中導入它們,如import util.ssh
或者from tweets import Retweet
(強烈希望你不介意這些名字,它們僅供參考)。 但是我應該如何使用Scala來做這些事情呢? 另外,我對JVM和Java沒有多少經驗,所以我在這里是一個完整的新手。
我不同意Jens ,雖然不是那么多。
我自己的建議是你在Maven的標准目錄布局上模擬你的工作。
以前版本的SBT(在SBT 0.9.x之前)會自動為您創建:
dcs@ayanami:~$ mkdir myproject
dcs@ayanami:~$ cd myproject
dcs@ayanami:~/myproject$ sbt
Project does not exist, create new project? (y/N/s) y
Name: myproject
Organization: org.dcsobral
Version [1.0]:
Scala version [2.7.7]: 2.8.1
sbt version [0.7.4]:
Getting Scala 2.7.7 ...
:: retrieving :: org.scala-tools.sbt#boot-scala
confs: [default]
2 artifacts copied, 0 already retrieved (9911kB/134ms)
Getting org.scala-tools.sbt sbt_2.7.7 0.7.4 ...
:: retrieving :: org.scala-tools.sbt#boot-app
confs: [default]
15 artifacts copied, 0 already retrieved (4096kB/91ms)
[success] Successfully initialized directory structure.
Getting Scala 2.8.1 ...
:: retrieving :: org.scala-tools.sbt#boot-scala
confs: [default]
2 artifacts copied, 0 already retrieved (15118kB/160ms)
[info] Building project myproject 1.0 against Scala 2.8.1
[info] using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7
> quit
[info]
[info] Total session time: 8 s, completed May 6, 2011 12:31:43 PM
[success] Build completed successfully.
dcs@ayanami:~/myproject$ find . -type d -print
.
./project
./project/boot
./project/boot/scala-2.7.7
./project/boot/scala-2.7.7/lib
./project/boot/scala-2.7.7/org.scala-tools.sbt
./project/boot/scala-2.7.7/org.scala-tools.sbt/sbt
./project/boot/scala-2.7.7/org.scala-tools.sbt/sbt/0.7.4
./project/boot/scala-2.7.7/org.scala-tools.sbt/sbt/0.7.4/compiler-interface-bin_2.7.7.final
./project/boot/scala-2.7.7/org.scala-tools.sbt/sbt/0.7.4/compiler-interface-src
./project/boot/scala-2.7.7/org.scala-tools.sbt/sbt/0.7.4/compiler-interface-bin_2.8.0.RC2
./project/boot/scala-2.7.7/org.scala-tools.sbt/sbt/0.7.4/xsbti
./project/boot/scala-2.8.1
./project/boot/scala-2.8.1/lib
./target
./lib
./src
./src/main
./src/main/resources
./src/main/scala
./src/test
./src/test/resources
./src/test/scala
因此,您將源文件放在myproject/src/main/scala
,用於主程序,或myproject/src/test/scala
,用於測試。
由於這不再起作用,有一些替代方案:
安裝giter8 ,克隆ymasory的sbt.g8模板並根據您的需要進行調整,並使用它。 例如,參見下面未修改的ymasory的sbt.g8模板的使用。 我認為這是開始新項目的最佳選擇之一,因為你對所有項目都有一個很好的概念。
$ g8 ymasory/sbt
project_license_url [http://www.gnu.org/licenses/gpl-3.0.txt]:
name [myproj]:
project_group_id [com.example]:
developer_email [john.doe@example.com]:
developer_full_name [John Doe]:
project_license_name [GPLv3]:
github_username [johndoe]:
Template applied in ./myproj
$ tree myproj
myproj
├── build.sbt
├── LICENSE
├── project
│ ├── build.properties
│ ├── build.scala
│ └── plugins.sbt
├── README.md
├── sbt
└── src
└── main
└── scala
└── Main.scala
4 directories, 8 files
使用softprops的sp 插件的np插件 。 在下面的示例中,插件在~/.sbt/plugins/build.sbt
,其設置在~/.sbt/np.sbt
,帶有標准的sbt腳本。 如果您使用paulp的sbt-extras,則需要在~/.sbt
的右側Scala版本子目錄下安裝這些內容,因為它為每個Scala版本使用單獨的配置。 在實踐中,這是我經常使用的那個。
$ mkdir myproj; cd myproj
$ sbt 'np name:myproj org:com.example'
[info] Loading global plugins from /home/dcsobral/.sbt/plugins
[warn] Multiple resolvers having different access mechanism configured with same name 'sbt-plugin-releases'. To avoid conflict, Remove duplicate project resolvers (`resolvers`) or rename publishing resolver (`publishTo`).
[info] Set current project to default-c642a2 (in build file:/home/dcsobral/myproj/)
[info] Generated build file
[info] Generated source directories
[success] Total time: 0 s, completed Apr 12, 2013 12:08:31 PM
$ tree
.
├── build.sbt
├── src
│ ├── main
│ │ ├── resources
│ │ └── scala
│ └── test
│ ├── resources
│ └── scala
└── target
└── streams
└── compile
└── np
└── $global
└── out
12 directories, 2 files
您可以使用mkdir
創建它:
$ mkdir -p myproj/src/{main,test}/{resource,scala,java}
$ tree myproj
myproj
└── src
├── main
│ ├── java
│ ├── resource
│ └── scala
└── test
├── java
├── resource
└── scala
9 directories, 0 files
現在,關於源布局。 Jens建議遵循Java風格。 嗯,Java目錄布局是一項要求 - 在Java中。 Scala沒有相同的要求,因此您可以選擇是否遵循它。
如果你遵循它,假設基礎包是org.dcsobral.myproject
,那么該包的源代碼將放在myproject/src/main/scala/org/dcsobral/myproject/
,等等用於子包。
偏離該標准的兩種常見方式是:
省略基本包目錄,僅創建子包的子目錄。
例如,假設我有包org.dcsobral.myproject.model
, org.dcsobral.myproject.view
和org.dcsobral.myproject.controller
,然后目錄將是myproject/src/main/scala/model
, myproject/src/main/scala/view
和myproject/src/main/scala/controller
。
將所有東西放在一起。 在這種情況下,所有源文件都在myproject/src/main/scala
。 這對小型項目來說已經足夠了。 實際上,如果您沒有子項目,則與上述相同。
這涉及目錄布局。
接下來,我們來談談文件。 在Java中,實踐是將每個類分隔在自己的文件中,該文件的名稱將遵循類的名稱。 這在Scala中也足夠好,但你必須注意一些例外。
首先,Scala具有Java所沒有的object
。 具有相同名稱的class
和object
被視為伴隨 ,它具有一些實際含義,但前提是它們位於同一文件中。 因此,將伴侶類和對象放在同一個文件中。
其次,Scala有一個稱為sealed class
(或trait
)的概念,它將子類(或實現object
)限制為在同一文件中聲明的子類。 這主要是為了創建具有模式匹配和窮舉檢查的代數數據類型。 例如:
sealed abstract class Tree
case class Node(left: Tree, right: Tree) extends Tree
case class Leaf(n: Int) extends Tree
scala> def isLeaf(t: Tree) = t match {
| case Leaf(n: Int) => println("Leaf "+n)
| }
<console>:11: warning: match is not exhaustive!
missing combination Node
def isLeaf(t: Tree) = t match {
^
isLeaf: (t: Tree)Unit
如果Tree
沒有sealed
,那么任何人都可以擴展它,使編譯器無法知道匹配是否是詳盡的。 無論如何, sealed
類一起放在同一個文件中。
另一個命名約定是命名包含package object
(對於該包) package.scala
。
最基本的規則是同一個包中的東西互相看見。 所以,把所有東西都放在同一個包里,你不需要關心自己看到了什么。
但Scala也有相對引用和導入。 這需要一些解釋。 假設我的文件頂部有以下聲明:
package org.dcsobral.myproject
package model
以下所有內容都將放在org.dcsobral.myproject.model
包中。 此外,不僅包裝內的所有內容都可見,而且org.dcsobral.myproject
內的所有org.dcsobral.myproject
也都可見。 如果我只是聲明了package org.dcsobral.myproject.model
,那么org.dcsobral.myproject
將不可見。
規則很簡單,但最初可能會讓人感到困惑。 此規則的原因是相對導入。 現在考慮該文件中的以下語句:
import view._
此導入可能是相對的 - 除非您使用_root_.
前綴,否則所有導入都可以是相對的_root_.
。 它可以引用以下包: org.dcsobral.myproject.model.view
, org.dcsobral.myproject.view
, scala.view
和java.lang.view
。 它還可以引用scala.Predef
名為view
的對象。 或者它可以是一個絕對導入,引用一個名為view
的包。
如果存在多個這樣的包,它將根據一些優先規則選擇一個。 如果您需要導入其他內容,可以將導入轉換為絕對導入。
此導入使view
包中的所有內容(無論它在何處)在其范圍內可見。 如果它發生在class
, object
或def
,則可見性將限制在此范圍內。 它導入所有東西,因為._
,這是一個通配符。
替代方案可能如下所示:
package org.dcsobral.myproject.model
import org.dcsobral.myproject.view
import org.dcsobral.myproject.controller
在這種情況下, 包 view
和controller
將是可見的,但您在使用它們時必須明確命名它們:
def post(view: view.User): Node =
或者您可以使用進一步的相對導入:
import view.User
import
語句還允許您重命名內容,或導入除了某些內容之外的所有內容。 有關詳細信息,請參閱相關文檔。
所以,我希望這能回答你所有的問題。
Scala支持並鼓勵Java / JVM的包結構,幾乎相同的建議適用:
<domain>.<module>.<layer>.<optional subpackage>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.