在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)
但这不起作用
我很少发现自己编写这样的代码了.原因在于,在你的例子中
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中,这意味着使用Iterable或Traversable- 但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)
的字面翻译
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.如果不是,请考虑以不同的方式做事,正如其他答案所解释的那样.