[英]“generics” in Scala?
In Java I would write 在Java中我会写
void foo(final Set<? extends SomeClass> someObjects) { /* ... */ }
What do I write in Scala? 我在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
. 也就是说,如果您只能访问集合中的元素,则不太可能需要它作为
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 ). 在scala中,这意味着使用
Iterable
或Traversable
- 但Scala中的这些类型在其类型参数中是协变的 (它们被声明为Iterable[+A]
- +
是声明 - 站点方差注释 )。 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: 然后你可以自由地
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
The reason that scala's Set[A]
is not covariant in A
is that it implements A => Boolean
(ie Function1 ), which is contravariant in its input. scala的
Set[A]
在A
不协变A
是它实现了A => Boolean
(即Function1 ),它在输入中是逆变的 。 Hence Set[A]
must be invariant in A
. 因此,
Set[A]
必须在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. 事实上,我现在使用
Set
作为谓词函数的实现细节更为常见。 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
. 如果您正在覆盖在一个Java类中某种方法,在前面加上
override
到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
. 这里
A <: SomeClass
意味着A
扩展了SomeClass
,你可以使用B >: SomeClass
来表达,而B
应该是SomeClass
的超类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.