13

Scalaクラスの「コンパニオンオブジェクト」は、クラスと同じ完全修飾名(つまり、同じパッケージ内の同じ名前)を持つシングルトンオブジェクトと見なすことができます。staticこれらは、Javaのメソッドの代わりとして、クラスのすべてのインスタンスに共通のユーティリティ関数を保持するために使用されます。

ただし、ドキュメントや質問のさまざまな場所で、コンパニオンオブジェクトを同じコンパイルユニットで定義する必要があると書かれています。たとえば、それらは同じファイルで定義する必要があります。コンパニオンオブジェクトをJavaオブジェクトに定義することはできませんREPLでは、これらは同じ入力行で定義する必要があるため、次の警告メッセージが表示されます。

warning: previously defined class Foo is not a companion to object Foo.
Companions must be defined together; you may wish to use :paste mode for this.

これは、コンパニオンオブジェクトを持つクラスと、同じ(完全に修飾された)名前を持つクラスとオブジェクトだけを区別する必要があることを意味します。この違いは何ですか?

4

1 に答える 1

17

クラスを呼び出しましょうclass SomeClass(ただし、たとえばaの場合もありますtrait)。

プライベートメンバー

コンパニオンオブジェクト(object SomeClass)のメソッドは、のインスタンスのプライベートメソッド/データにアクセスできclass SomeClassます。

コンパニオンオブジェクトがクラスのパブリックインターフェイスのみを使用する場合(たとえば、定数を定義するだけの場合)、実際的な違いはありません。ただし、ユーティリティ関数にプライベートメンバーへのアクセスを許可すると便利な場合がいくつかあります。たとえば、パブリックインターフェイスでセッターを公開せずに、のプライベートメンバーを設定object SomeClassするファクトリメソッドを定義できます。したがって、このような場合は、の定義をと同じコンパイル単位に入れて、コンパニオンオブジェクトを定義する必要があります。applyclass SomeClassobject SomeClassclass SomeClass

もう1つの違いは、コンパイラがタイプ(およびそのスーパータイプ)のコンパニオンオブジェクトで暗黙を検索することです。したがって、のコードで定義する暗黙的な変換を使用している場合はclass SomeClass、コンパニオンオブジェクトでそれらを定義する必要があります。

コメントコメント

この2つの組み合わせは、同じコンパイル単位の制限についても説明しています。

  • scalacプライベートメンバーが何を呼び出すobject SomeClassかがわかるまでコンパイルできません。class SomeClass
  • scalacclass SomeClass何が暗黙的に呼び出されるかがわかるまでコンパイルできません。したがって、コンパニオンオブジェクトは遅くとも。までにコンパイルする必要がありますclass SomeClass

したがって、それらは同時にコンパイルする必要があります。さらに、現在のコンパイラは明らかに別々のファイルを別々にコンパイルし(複数のファイルにクラスを分割するためのサポートの欠如を参照)、同じコンパイル単位に制限しています。

于 2012-07-22T22:01:06.163 に答える