簡體   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