gpt4 book ai didi

Scala应用程序结构

转载 作者:行者123 更新时间:2023-12-03 05:40:30 25 4
gpt4 key购买 nike

我现在正在学习 Scala,我想编写一些愚蠢的小应用程序,比如控制台 Twitter 客户端,或者其他什么。问题是,如何在磁盘上和逻辑上构建应用程序。我知道 python,在那里我会创建一些带有类的文件,然后将它们导入到主模块中,例如 import util.sshfrom tweets import Retweet (强烈希望你不会介意这些名字,它们仅供引用)。但是如何应该我用 Scala 做这些东西?另外,我对 JVM 和 Java 没有太多经验,所以我在这里完全是新手。

最佳答案

我将不同意 Jens ,在这里,虽然不是那么多。

项目布局

我自己的建议是,您可以在 Maven's standard directory layout 上模拟您的努力。 .

以前版本的 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 和 sbt.g8

安装 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

np插件

使用软 Prop 的 np plugin对于 sbt。在下面的示例中,插件在 ~/.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.vieworg.dcsobral.myproject.controller ,那么目录将是 myproject/src/main/scala/model , myproject/src/main/scala/viewmyproject/src/main/scala/controller .
  • 把所有东西放在一起。在这种情况下,所有源文件都在 myproject/src/main/scala 中。 .这对于小型项目来说已经足够了。其实,如果你没有子项目,就和上面一样。

  • 这涉及目录布局。

    文件名

    接下来,让我们谈谈文件。在 Java 中,实践是将每个类分隔在其自己的文件中,其名称将跟随类的名称。这在 Scala 中也足够好,但您必须注意一些异常(exception)情况。

    首先,Scala有 object ,这是Java没有的。一个 classobject同名被认为是同伴,这有一些实际意义,但前提是它们在同一个文件中。因此,将伴随类和对象放在同一个文件中。

    其次,Scala 有一个被称为 sealed class 的概念。 (或 trait ),它将子类(或实现 object s)限制为在同一文件中声明的那些。这主要是为了创建具有详尽检查的模式匹配的代数数据类型。例如:
    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 中的所有内容都可见。也将可见。如果我刚刚声明 package org.dcsobral.myproject.model相反,然后 org.dcsobral.myproject将不可见。

    规则很简单,但一开始可能会让人们有点困惑。这条规则的原因是相对进口。现在考虑该文件中的以下语句:
    import view._

    这个导入可能是相对的——所有的导入都可以是相对的,除非你用 _root_. 作为前缀。 .可以引用以下包: org.dcsobral.myproject.model.view , org.dcsobral.myproject.view , scala.viewjava.lang.view .它还可以引用名为 view 的对象。内 scala.Predef .或者它可能是引用名为 view 的包的绝对导入.

    如果存在多个这样的包,它会根据一些优先规则选择一个。如果您需要导入其他内容,您可以将导入变成绝对导入。

    此导入使 view 中的所有内容都在包(无论它在哪里)在其范围内可见。如果它发生在 class 内, 和 objectdef ,那么可见性将仅限于此。由于 ._,它导入了所有内容,这是一个通配符。

    另一种可能如下所示:
    package org.dcsobral.myproject.model
    import org.dcsobral.myproject.view
    import org.dcsobral.myproject.controller

    在这种情况下,包 viewcontroller将是可见的,但您必须在使用它们时明确命名它们:
    def post(view: view.User): Node =

    或者您可以使用进一步的相对导入:
    import view.User
    import语句还使您能够重命名内容,或导入除某些内容之外的所有内容。有关更多详细信息,请参阅有关它的相关文档。

    所以,我希望这能回答你所有的问题。

    关于Scala应用程序结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5910791/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com