In Java I would write
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
What do I write in Scala?
def foo(someObjects : Set[AnyRef[SomeClass])
But this doesn't work
In Java I would write
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
What do I write in Scala?
def foo(someObjects : Set[AnyRef[SomeClass])
But this doesn't work
I rarely find myself writing code like this any more. The reason is that, in your example
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
// ^^^^^^^^^^
// use-site variance annotation
The variance annotation denotes you can only access the collection, not update it. It's highly probable that you could re-write the method as follows
void foo(final Collection<? extends SomeClass> someObjects) { /* ... */ }
That is, if you can only access elements in the set, it's unlikely that you need it to be a Set
. In scala, this means using Iterable
or Traversable
- but these types in Scala are covariant in their type parameter (they are declared Iterable[+A]
- the +
is a declaration-site variance annotation). Hence there is no need for a use-site variance annotation:
def foo(itr: Iterable[SomeClass])
Then you can pass a Set[SomeClassImpl]
freely into this method:
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
The reason that scala's Set[A]
is not covariant in A
is that it implements A => Boolean
(i.e. Function1), which is contravariant in its input. Hence Set[A]
must be invariant in A
. Some chump has asked this before.
In fact, it's much more common that I now use Set
as an implementation detail of a predicate function. So, for example:
def bar(p: SomeClass => Boolean)
In this event; you could use:
scala> bar(res1.toSet[T])
The literal translation for
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
is
def foo(someObjects: Set[_ <: SomeClass]) { /* ... */ }
or
def foo(someObjects: Set[_ <: SomeClass]): Unit = { /* ... */ }
If you are overriding some method in a Java class, prepend override
to def
. If you are not, please consider doing things in a different manner, as explained by the other answers.
You can define the dependency by using a type bound:
def foo[A <: SomeClass]( someObjects: Set[A] ): Unit = ...
Here A <: SomeClass
means that A
extends SomeClass
, and you can use B >: SomeClass
to express than B
should be a super class of SomeClass
.