2015-08-24 83 views
0

考慮下面的代碼理解存在類型斯卡拉

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

Field[A] forSome {type A} - 您可以使用A作爲Type(參數化字段類型A),因爲您將此類型聲明爲大括號,存在類型可以說您可以接受任何類型,在您的情況下,當方法addField爲參數化,使用Seq [Field]與存在類型是解決方案之一,因爲這個集合將存儲不同的類型。

+0

的一小段路。如果我簡單地聲明'在代碼的頂部類型A'和使用'變種fields = Set [Field [A]]()'它仍然不能編譯。是因爲'Field [A] for {Some A}'在Field [A]'的上下文中創建了'Type A'?如果這是有道理的。 –

+0

如果你聲明類型是這樣的:type A = Field [B] forSome {type B}它將被編譯,所以A forSome {type A}就是特殊的scala結構,它使你能夠創建存在類型,這就是說它可以是任何類型 – grotrianster

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被聲明爲類型參數,即它將被使用來定義。

當你把兩個StringFieldIntFieldfields變種,我想你想字段是任何種類FieldSet。所以通常你告訴編譯器,通過一個通配符:

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

這基本上是寫

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