我看到了问题的答案:Can all usages of forSome
be replaced by an equivalent usage of _
?,
但是不明白真正的情况是什么?" _"不能使用" for Some"。
我在Programming in Scala书中读到:
存在类型是语言的完全支持部分,但是在 实践它们主要在从Scala访问Java类型时使用。 我创建了Scala项目并向其引用了Java:
Scala的:
object Main {
def main(args: Array[String]): Unit = {
type Test = java.util.Collection[T] forSome { type T }
val contents: Test = (new Wild).contents
type Test2 = java.util.Collection[_]
val contents2: Test2 = (new Wild).contents
// foo((new Wild).contents2) // won't compile
foo1((new Wild).contents2)
foo1((new Wild).contents3)
foo2((new Wild).contents3)
}
def foo(xs: java.util.Map[T, T] forSome { type T }) {}
def foo1(xs: java.util.Map[_, _]) {}
def foo2(xs: java.util.Map[_, _ <: java.lang.Number]) {}
}
爪哇:
public class Wild {
public Collection<?> contents() {
return null;
}
public Map<?, ?> contents2() {
return null;
}
public Map<?, ? extends Number> contents3() {
return null;
}
}
在所有情况下,我都能够取代&#34; forSome&#34;与&#34; _&#34;。 那么什么是真实案例,其中&#34; forSome&#34;有必要的?请提供简单的工作示例。
答案 0 :(得分:10)
这是一个相当简单的例子。
val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
请注意,我只能将相同包含的类型集存储到列表中。我无法做到,例如这样:
val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set("a", "b", "c"))
listOfSets
的类型在没有forSome
的情况下无法表达。事实上,
val listOfSets2: List[Set[_]]
相当于
val listOfSets2: List[Set[T] forSome { type T }]
这意味着该列表可以包含不同类型的集合,因此这两种方法都有效:
val listOfSets2: List[Set[_]] = List(Set(1, 2, 3), Set(4, 5, 6))
val listOfSets2: List[Set[_]] = List(Set(1, 2, 3), Set("a", "b", "c"))
有趣的是,如果您将Scala解释器作为scala -feature
运行并尝试执行此答案中的第一行代码,您将获得有关带有通配符的存在类型的无法表达的警告:
scala> val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
<console>:7: warning: the existential type List[Set[T]] forSome { type T }, which cannot be expressed by wildcards, should be enabled
by making the implicit value scala.language.existentials visible.
This can be achieved by adding the import clause 'import scala.language.existentials'
or by setting the compiler option -language:existentials.
See the Scala docs for value scala.language.existentials for a discussion
why the feature should be explicitly enabled.
val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
^
listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
还有另一个例子。假设您要将类映射到该类的单个实例。这可以用这种类型表示:
val classInstanceMap: Map[Class[T], T] forSome { type T }
如果没有forSome
,则无法写出正确的类型 - 没有其他方法可以“关联”键和值的类型。例如,此类型带有通配符:
val invalidClassInstanceMap: Map[Class[_], _]
相当于
val invalidClassInstanceMap: Map[Class[K] forSome { type K }, V] forSome { type V }
此处K
和V
根本不相关,此外,对于任意Class[T]
,密钥可以是T
的任意实例,但所有值都应具有相同的类型