"forSome"的所有用法都可以用"_`的等效用法代替吗?"

use*_*319 5 scala

我看到了问题的答案:所有用法都forSome可以用等效用法代替_吗?,但不明白什么是"_"不能用来代替"forSome"的真实情况.我在Scala编程书中读到:

存在类型是语言的完全支持部分,但实际上它们主要用于从Scala访问Java类型时.我创建了Scala项目并引用了Java一个:

斯卡拉:

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

Java的:

public class Wild {
    public Collection<?> contents() {
        return null;
    }
    public Map<?, ?> contents2() {
        return null;
    }
    public Map<?, ? extends Number> contents3() {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

在所有情况下,我都可以用"_"替换"forSome".那么"forSome"是必要的真实案例是什么?请提供简单的工作示例.

Vla*_*eev 10

这是一个相当简单的例子.

val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set(4, 5, 6))
Run Code Online (Sandbox Code Playgroud)

请注意,我只能将相同包含类型的集合存储到列表中.我不能这样做:

val listOfSets: List[Set[T]] forSome { type T } = List(Set(1, 2, 3), Set("a", "b", "c"))
Run Code Online (Sandbox Code Playgroud)

没有这种类型listOfSets是无法形容的forSome.确实,

val listOfSets2: List[Set[_]]
Run Code Online (Sandbox Code Playgroud)

相当于

val listOfSets2: List[Set[T] forSome { type T }]
Run Code Online (Sandbox Code Playgroud)

这意味着列表可以包含不同类型的集合,因此这两个工作:

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

有趣的是,如果你运行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))
Run Code Online (Sandbox Code Playgroud)

还有另一个例子.假设您要将类映射到该类的单个实例.这可以用这种类型表示:

val classInstanceMap: Map[Class[T], T] forSome { type T }
Run Code Online (Sandbox Code Playgroud)

没有forSome你不能写出正确的类型 - 没有其他方法来"关联"键和值的类型.例如,这种类型带有通配符:

val invalidClassInstanceMap: Map[Class[_], _]
Run Code Online (Sandbox Code Playgroud)

相当于

val invalidClassInstanceMap: Map[Class[K] forSome { type K }, V] forSome { type V }
Run Code Online (Sandbox Code Playgroud)

这里KV在所有都没有关系,而且,键可以任意情况下Class[T]任意T,但所有的值应该具有相同的类型.