繁体   English   中英

了解Scala中的存在类型

[英]Understanding existential types in Scala

考虑以下代码

import scala.collection.mutable.Set
import scala.collection.mutable.HashMap

// classes to create field types that do conversion of string to other types

trait Field[A] {
    def convert(x: String): A // Need to define convert for the trait, too.
}

case class IntField extends Field[Int] {
    override def convert(x: String): Int = x.toInt
}

case class StringField extends Field[String] {
    override def convert(x: String): String = x
}

// this function can take any Field type and return a HashMap, 
// more important here is type of key not the value of HashMap
// which has to match with value returned from Field.convert()

def someFunc[A](field: Field[A]): HashMap[A, Int] = {
    val index = new HashMap[A, Int]()
    val data = List("111", "222", "333")

    for (line <- data) {
        val values: A = field.convert(line)
        index.put(values, 0)
    }
    index
}

// this empty set will be populated with Field objects, and here I get an error
var fields = Set[Field[A]]()

def addField[A](field: Field[A]): Unit = fields += field

addField(StringField())
addField(IntField())

for (field <- fields) println(someFunc(field))

// RESULT
Map(333 -> 0, 222 -> 0, 111 -> 0) // HashMap[String, Int]
Map(111 -> 0, 333 -> 0, 222 -> 0) // HashMap[Int, Int]

上面的代码无法编译, not found: type A错误not found: type A创建var fieldsnot found: type A 现在,当我将这一行更改为:

var fields = Set[Field[A] forSome {type A}]()

一切都可以编译,但是我不完全了解这里会发生什么。 我了解执行var fields = Set[Field[A]]()不存在类型A,但是其他行如何解决此问题,它甚至是正确的解决方案,还是恰好在这种情况下起作用?

Field[A] forSome {type A} -您可以将A用作类型(参数化类型为A的参数字段),因为在大括号中声明了该类型,存在性类型是一种表示您可以接受任何类型的方式当方法addField为参数时,将Seq [Field]与存在类型一起使用是一种解决方案,因为此集合将存储不同的类型。

您的问题可能不是真正存在的类型,而是泛型的定义和用法,因为var fields = A也不会编译。

var fields = Set[Field[A]]()

A未定义,因为您没有在范围内的任何地方声明它。

trait Field[A] {

def someFunc[A](field: Field[A]): HashMap[A, Int] = {

def addField[A](field: Field[A]): Unit = fields += field

A声明为类型参数,即将按用途定义。

当你把两只StringFieldIntField在你的fields变种,我想你想的字段是一个Set任何类型的Field 因此,通常您通过通配符告诉编译器:

var fields = Set[Field[_]]()

这本质上是写作的捷径

var fields = Set[Field[A] forSome {type A}]()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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