考虑以下代码
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
时错误为var fields
- 。现在,当我将此行更改为:
var fields = Set[Field[A] forSome {type A}]()
一切都在编译,但我并不完全理解这里发生的事情。我理解,当执行var fields = Set[Field[A]]()
类型A不存在但其他行如何解决此问题时,它是否是正确的解决方案,或者恰好在这种情况下工作?
答案 0 :(得分:0)
Field[A] forSome {type A}
- 您可以使用A作为类型(带有类型A的参数化字段),因为您在大括号中声明此类型,存在类型是一种表示您可以接受任何类型的方式,在您的情况下方法addField是参数化,使用具有存在类型的Seq [Field]是一个解决方案,因为这个集合将存储不同的类型。
答案 1 :(得分:0)
您的问题可能不是真实的存在类型,而是通用类型的定义和用法,因为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被声明为类型参数,即它将由用法定义。
当您将StringField
和IntField
放在fields
var中时,我想您希望字段为任意类型的Set
Field
。所以通常你通过通配符告诉编译器:
var fields = Set[Field[_]]()
这基本上是写作的简短方法
var fields = Set[Field[A] forSome {type A}]()