繁体   English   中英

如何在 Scala 中为存在类型显式指定参数化类型?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM