パッケージオブジェクトとは何ですか?概念ではなく、その使用法ですか?
私は例を動作させようとしましたが、動作するようになった唯一のフォームは次のとおりでした:
package object investigations {
val PackageObjectVal = "A package object val"
}
package investigations {
object PackageObjectTest {
def main(args: Array[String]) {
println("Referencing a package object val: " + PackageObjectVal)
}
}
}
私がこれまでに行った観察は次のとおりです。
package object _root_ { ... }
許可されていません(合理的です)。
package object x.y { ... }
も許可されていません。
パッケージオブジェクトは直接の親パッケージで宣言する必要があり、上記のように記述した場合は、中括弧で区切られたパッケージ宣言フォームが必要です。
それらは一般的に使用されていますか?もしそうなら、どのように?
通常、パッケージオブジェクトは、対応するパッケージ内のpackage.scala
という別のファイルに配置します。ネストされたパッケージ構文を使用することもできますが、これは非常に珍しいことです。
パッケージオブジェクトの主な使用例は、パッケージで定義されたAPIを使用するときに、パッケージ内およびパッケージ外のさまざまな場所で定義が必要な場合です。以下に例を示します。
// file: foo/bar/package.scala
package foo
package object bar {
// package wide constants:
def BarVersionString = "1.0"
// or type aliases
type StringMap[+T] = Map[String,T]
// can be used to emulate a package wide import
// especially useful when wrapping a Java API
type DateTime = org.joda.time.DateTime
type JList[T] = Java.util.List[T]
// Define implicits needed to effectively use your API:
implicit def a2b(a: A): B = // ...
}
これで、そのパッケージオブジェクト内の定義がパッケージfoo.bar
内で利用可能になりました。さらに、そのパッケージ外の誰かがfoo.bar._
をインポートすると、定義がインポートされます。
この方法により、ライブラリを効果的に使用するために追加のインポートをAPIクライアントに要求することを防ぐことができます。スカラスイングでは、書く必要があります
import swing._
import Swing._
onEDT
とTuple2
からDimension
への暗黙的な変換のようなすべての長所を持ちます。
Moritzの答えはスポットオンですが、注意すべきもう1つの点は、パッケージオブジェクトがオブジェクトであるということです。とりわけ、これは、ミックスイン継承を使用して、特性からそれらを構築できることを意味します。 Moritzの例は、
package object bar extends Versioning
with JodaAliases
with JavaAliases {
// package wide constants:
override val version = "1.0"
// or type aliases
type StringMap[+T] = Map[String,T]
// Define implicits needed to effectively use your API:
implicit def a2b(a: A): B = // ...
}
ここで、バージョニングは抽象特性であり、パッケージオブジェクトには「バージョン」メソッドが必要であり、JodaAliasesとJavaAliasesは便利なタイプエイリアスを含む具体的な特性です。これらの特性はすべて、さまざまなパッケージオブジェクトで再利用できます。
パッケージオブジェクトの主な使用例は、パッケージで定義されたAPIを使用するときに、パッケージ内およびパッケージ外のさまざまな場所で定義が必要な場合です。
そうではないScala 3、2020年半ばにリリース予定、 Dotty 、 ここに :
トップレベルの定義
すべての種類の定義はトップレベルで記述できます。
パッケージオブジェクトは不要になり、段階的に廃止されます。
package p
type Labelled[T] = (String, T)
val a: Labelled[Int] = ("count", 1)
def b = a._2
def hello(name: String) = println(i"hello, $name)