8

賢明であろうとなかろうと、私は Scala シングルトン、つまりクラスやトレイトの構築されたインスタンスではなく「オブジェクト」を介して実装されたオブジェクトのみを受け入れたいメソッドを書いています。どのタイプの Scala シングルトンも受け入れる必要があるため、"MySingleton.type" は使用できません。

APIドキュメントには記載されていない非常に奇妙な構造「scala.Singleton」に出くわしましたが、うまくいくようです:

scala> def check( obj : Singleton ) = obj
check: (obj: Singleton)Singleton

scala> check( Predef )
res0: Singleton = scala.Predef$@4d3e9963

scala> check ( new java.lang.Object() )
<console>:9: error: type mismatch;
 found   : java.lang.Object
 required: Singleton
              check ( new java.lang.Object() )

scala> check( Map )
res3: Singleton = scala.collection.immutable.Map$@6808aa2d

scala> check( Map.empty[Any,Any] )
<console>:9: error: type mismatch;
 found   : scala.collection.immutable.Map[Any,Any]
 required: Singleton
              check( Map.empty[Any,Any] )

ただし、かなり不可解なことに (私には)、明示的に構築された文字列はそうではありませんが、文字列リテラルはシングルトンとして受け入れられます。

scala> check( "foo" )
res7: Singleton = foo

scala> check( new String("foo") )
<console>:9: error: type mismatch;
 found   : java.lang.String
 required: Singleton
              check( new String("foo") )

文字列リテラルがシングルトンに準拠するのはなぜですか? シングルトン型が指定することになっているものを誤解していますか?

4

3 に答える 3

9

まず、シングルトン型とは?型が値のセットであると考える場合、シングルトン型は、要素が 1 つだけのセットです。

最も一般的には、トップレベルのオブジェクトがそのようなセットに存在できます。

scala> object X
defined module X

scala> X: X.type
res41: X.type = X$@131d1cb

scala> res41: Singleton
res42: Singleton = X$@131d1cb

より一般的には、安定した値はシングルトン型を形成できます。

scala> object X { val y: String = "boo" }
defined module X

scala> X.y: X.y.type
res44: X.y.type = boo

scala> res44: Singleton
res45: Singleton = boo

yが adefまたは a の場合var、時間の経過とともに値が同じではない可能性があるため、修飾されなくなります。そのため、コンパイラは、シングルトン型が唯一無二の値を分類することを保証できません。

scala> object X { def y: String = "boo" }
defined module X

scala> X.y: X.y.type
<console>:12: error: stable identifier required, but X.y found.
              X.y: X.y.type
                     ^

scala> object X { var y: String = "boo" }
defined module X

scala> X.y: X.y.type
<console>:12: error: stable identifier required, but X.y found.
              X.y: X.y.type
                     ^

もう 1 つの制限: AnyVals はシングルトン型を形成できません。これは、言語仕様が特に に制限しているためAnyRefです。

Paul Phillips は、リテラルのシングルトン型を表現できるブランチをキュレートしています。

val xs: Stream[0.type](0)
val ys: Stream[0.type](0, 1) // does not compile
val x = xs.head // inferred type is 0.type, we statically know that this can only be 0!
于 2012-07-22T07:01:13.023 に答える
6

私が知る限り、すべての不変参照は、文字列だけでなく、このコンテキストではシングルトンと見なされます。たとえば、invoke check(5)、またはval foo = List(1,2,3); check(foo). var bar = List(1,2,3); check(bar)ただし、動作しません。

この動作から判断すると、参照が変更されない (またはこのコンテキストでは「最終的」である) とコンパイラが判断できる場合、参照はシングルトンと見なされると思います。

于 2012-07-21T18:45:32.527 に答える
4

最も簡単な手がかりは、Scala リファレンスのセクション 3.2.1 の第 3 章から得られると思います。

シングルトン型は p.type の形式で、p は scala.AnyRef に準拠 (§6.1) すると予想される値を指すパスです。型は、null と p で示される値で構成される値のセットを示します。

安定型は、singleton 型か、trait scala.Singleton のサブタイプとして宣言されている型のいずれかです。

安定した型の概念は重要であり、このトレイトによって、他の方法では安定しているとは見なされないものを安定していると宣言できるようになります。

于 2012-07-22T17:28:01.813 に答える