Javaで私は書くだろう
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
Scalaで何を書く?
def foo(someObjects : Set[AnyRef[SomeClass])
しかし、これは機能しません
このようなコードを書くことはめったにありません。その理由は、あなたの例では
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
// ^^^^^^^^^^
// use-site variance annotation
バリアンス アノテーションは、コレクションへのアクセスのみが可能であり、更新はできないことを示しています。次のようにメソッドを書き直すことができる可能性が非常に高いです
void foo(final Collection<? extends SomeClass> someObjects) { /* ... */ }
つまり、セット内の要素にしかアクセスできない場合は、Set
. scala では、これはIterable
orを使用することを意味しますが、ScalaTraversable
のこれらの型は型パラメーターで共変です (それらは宣言されています- これは宣言サイト分散注釈です)。したがって、使用部位の差異の注釈は必要ありません。Iterable[+A]
+
def foo(itr: Iterable[SomeClass])
Set[SomeClassImpl]
次に、このメソッドにa を自由に渡すことができます。
scala> trait T; class S extends T
defined trait T
defined class S
scala> def foo(itr: Iterable[T]) = println(itr.isEmpty)
foo: (itr: Iterable[T])Unit
scala> Set(new S)
res1: scala.collection.immutable.Set[S] = Set(S@e1ed5b)
scala> foo(res1)
false
scalaSet[A]
が in で共変でない理由は、その入力で反変である(つまりFunction1 ) をA
実装しているためです。したがって、 で不変でなければなりません。一部のチャンプが以前にこれを尋ねました。A => Boolean
Set[A]
A
実際、述語関数の実装の詳細Set
として使用することは、はるかに一般的です。たとえば、次のようになります。
def bar(p: SomeClass => Boolean)
このイベントでは; あなたが使用することができます:
scala> bar(res1.toSet[T])
の直訳は
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
は
def foo(someObjects: Set[_ <: SomeClass]) { /* ... */ }
また
def foo(someObjects: Set[_ <: SomeClass]): Unit = { /* ... */ }
Java クラスのメソッドをオーバーライドする場合は、先頭override
にdef
. そうでない場合は、他の回答で説明されているように、別の方法で物事を行うことを検討してください。
型バインドを使用して依存関係を定義できます。
def foo[A <: SomeClass]( someObjects: Set[A] ): Unit = ...
ここでは、 を拡張A <: SomeClass
することを意味し、 のスーパークラスである必要があることを表現するために使用できます。A
SomeClass
B >: SomeClass
B
SomeClass