斯卡拉的"仿制药"?

Pau*_*zie 3 generics scala

在Java中我会写

void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

我在Scala中写什么?

def foo(someObjects : Set[AnyRef[SomeClass])
Run Code Online (Sandbox Code Playgroud)

但这不起作用

oxb*_*kes 6

我很少发现自己编写这样的代码了.原因在于,在你的例子中

void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
//                ^^^^^^^^^^
//                use-site variance annotation
Run Code Online (Sandbox Code Playgroud)

方差注释表示你只能访问收藏,不更新.您很可能可以按如下方式重写该方法

void foo(final Collection<? extends SomeClass> someObjects) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

也就是说,如果你只能访问集合中的元素,那么你不太可能需要Set.在scala中,这意味着使用IterableTraversable- 但Scala中的这些类型其类型参数中是协变的(它们被声明Iterable[+A]- 它+声明 - 站点方差注释).因此,不需要使用站点方差注释:

def foo(itr: Iterable[SomeClass])
Run Code Online (Sandbox Code Playgroud)

然后你可以Set[SomeClassImpl]自由地传递给这个方法:

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
Run Code Online (Sandbox Code Playgroud)

scala Set[A]不是协变的原因A是它实现了A => Boolean(即Function1),它在输入中是逆变的.因此Set[A]必须是不变的A.有些笨蛋之前问过这个问题.

实际上,我现在将其Set用作谓词函数的实现细节更为常见.所以,例如:

def bar(p: SomeClass => Boolean)
Run Code Online (Sandbox Code Playgroud)

在这种情况下; 你可以使用:

scala> bar(res1.toSet[T])
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 5

的字面翻译

void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

def foo(someObjects: Set[_ <: SomeClass]) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

要么

def foo(someObjects: Set[_ <: SomeClass]): Unit = { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

如果要覆盖Java类中的某些方法,请在前面override添加def.如果不是,请考虑以不同的方式做事,正如其他答案所解释的那样.