[英]How do you explicitly specify a parameterized type for an existential type in Scala?
在Scala 编程中,给出了以下示例来说明如何使用通配符引用 Java class。 javaSet2ScalaSet
方法采用类型 T。通常,您始终可以显式提供参数化类型。 但在(new Wild).contents
存在的情况下,普通类型参数是不可接受的。
当在没有类型参数的情况下调用javaSet2ScalaSet
时,编译器能够执行一些魔术并推断出适当的参数。 查看编译器使用 scalac –Xprint:typer 提供的内容表明它为 T 分配了一个值?0。这不能手动提供。
这是仅适用于推断类型的特殊情况,还是有某种方法可以显式提供类型?
// This is a Java class with wildcards
public class Wild {
Collection<?> contents() {
Collection<String> stuff = new Vector<String>();
stuff.add("a");
stuff.add("b");
stuff.add("see");
return stuff;
}
}
import scala.collection.mutable.Set
import java.util.Collection
abstract class SetAndType {
type Elem
val set: Set[Elem]
}
def javaSet2ScalaSet[T](jset: Collection[T]): SetAndType = {
val sset = Set.empty[T] // now T can be named!
val iter = jset.iterator
while (iter.hasNext)
sset += iter.next()
return new SetAndType {
type Elem = T
val set = sset
}
}
val setAndType = javaSet2ScalaSet((new Wild).contents)
这只是语法限制,而不是固有限制。 以下是您可以声明它的方法:
def javaSet2ScalaSet[C <: Collection[T] forSome { type T }](jset: C): SetAndType = {
val sset = Set.empty[T forSome { type T }]
val iter = jset.iterator
while (iter.hasNext)
sset += iter.next()
return new SetAndType {
type Elem = T forSome { type T }
val set = sset
}
}
(Q1)>>这是仅适用于推断类型的特殊情况。 <<
编译器不会将您的 Java 集合的类型推断为 Collection 类型。 它只知道它是一个包含某种类型元素的集合。
(Q2) >> 或者有什么方法可以明确地提供类型? <<
不,不提供存在类型。 它不是要绑定的自由变量(因为它已经绑定了)。
这样看:假设您能够提供类型。 然后,您会期望编译器检查提供的类型是否与您的 Java 集合中的元素类型匹配。 但是编译器无法确定这一点。 因此,如果它们不匹配,您无论如何只能在运行时发现。
如果您想告诉 Scala 编译器您知道 java 集合中的元素是 String 类型(例如,您想调用 x.length),那么您可以使用 asInstanceOf[String] 强制转换元素。 但这不会引入类型安全。 您将再次仅在运行时发现它是否不正确。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.