2011-01-06 38 views
2

我需要什麼是一個類XI可以用一個Map來構造,它將Strings帶入其他Strings或Maps中,將Strings轉換爲Strings,然後任意數量的其他實例十,用我有限的斯卡拉的把握,我知道我能做到這一點:如何在另一個構造函數中獲取類似地圖的糖

class Person (stringParms : Map[String, String], 
     mapParms : Map[String, Map[String, String]], 
     children : List[X]) { 
} 

但是,這並不顯得很斯卡拉上下的我」(「Scalish」「Scalerific」「Scalogical」???) d喜歡能夠做到的是:

Person bob = Person("name" -> "Bob", "pets" -> ("cat" -> "Mittens", "dog" -> "Spot"), "status" -> "asleep", 
     firstChild, secondChild) 

我知道我ca n通過使用伴侶對象擺脫「新」,我確信我可以看看斯卡拉可變參數。我想知道的是:

  1. 我該如何使用 - >(或者一些類似似是而非的操作符)構造要在構造中構建Map的元素?
  2. 如何定義單個映射,以便它可以在兩個完全不同的類型之間進行類似Option的選擇,或者成爲遞歸樹,其中每個(指定)節點指向一個String形式的葉或另一個像它自己的節點?

的遞歸版本真正吸引我,因爲,雖然它並沒有解決一個問題,我今天居然有,它巧妙地映射到JSON的只包含對象和字符串(不含數字陣列)的一個子集。

任何幫助,一如既往,非常感謝。

+2

注意到,有重複的參數和多個參數列表,所以你可以這樣寫頭:'class Person [X](str:Map [String,String] *)(map: Map [String,Map [String,String]] *)(a:List [X] *)' – coubeatczech 2011-01-06 12:53:24

+0

@coubeatczech - děkuji。我知道有多個參數列表,但我從未想到這可能是對它們的完美使用。我必須調查如果第一個列表爲空,會發生什麼。 – Malvolio 2011-01-06 19:41:30

回答

3

->只是一個語法糖做成一對(A, B),所以你也可以使用它。 Map object需要對一個可變參數:

def apply [A, B] (elems: (A, B)*) : Map[A, B] 

你應該先看看The Architecture of Scala Collections如果你有興趣在模仿集合庫。

話雖如此,我不認爲你提出Person簽名看起來像Map,因爲它需要的變量參數,但children不與其他(String, A)主題不斷。如果你說"child1" -> Alice,並在內部存儲Alice seperately,你可以定義:

def apply(elems: (String, Any)*): Person 
在同伴對象

。如果Any太鬆,你可以定義PersonElem特質,

def apply(elems: (String, PersonElem)*): Person 

和隱式轉換之間StringMap[String, String]Person等,以PersonElem

1

這讓你幾乎在那裏。還有一個地圖我不能輕易擺脫。

基本的方法是有一個有點人造的參數類型,它從一個普通的類型繼承。這種方法申請方法只需要一個可變參數。

使用隱式轉換方法我擺脫難看的構造函數爲參數類型

case class Child 

case class Person(stringParms: Map[String, String], 
    mapParms: Map[String, Map[String, String]], 
    children: List[Child]) { } 

sealed abstract class PersonParameter 
case class MapParameter(tupel: (String, Map[String, String])) extends PersonParameter 
case class StringParameter(tupel: (String, String)) extends PersonParameter 
case class ChildParameter(child: Child) extends PersonParameter 

object Person { 
    def apply(params: PersonParameter*): Person = { 

     var stringParms = Map[String, String]() 
     var mapParms = Map[String, Map[String, String]]() 
     var children = List[Child]() 
     for (p ← params) { 
      p match { 
       case StringParameter(t) ⇒ stringParms += t 
       case MapParameter(t) ⇒ mapParms += t 
       case ChildParameter(c) ⇒ children = c :: children 
      } 
     } 
     new Person(stringParms, mapParms, children) 
    } 
    implicit def tupel2StringParameter(t: (String, String)) = StringParameter(t) 
    implicit def child2ChildParameter(c: Child) = ChildParameter(c) 
    implicit def map2MapParameter(t: (String, Map[String, String])) = MapParameter(t) 

    def main(args: Array[String]) { 
     val firstChild = Child() 
     val secondChild = Child() 
     val bob: Person = Person("name" -> "Bob","pets" -> Map("cat" -> "Mittens", "dog" -> "Spot"),"status" 
-> "asleep", 
     firstChild, secondChild) 

     println(bob) 
    } } 
0

這裏有一種方法:

sealed abstract class PersonParam 
object PersonParam { 
    implicit def toTP(tuple: (String, String)): PersonParam = new TupleParam(tuple) 
    implicit def toMap(map: (String, Map[String, String])): PersonParam = new MapParam(map) 
    implicit def toSP(string: String): PersonParam = new StringParam(string) 
} 

class TupleParam(val tuple: (String, String)) extends PersonParam 
class MapParam(val map: (String, Map[String, String])) extends PersonParam 
class StringParam(val string: String) extends PersonParam 

class Person(params: PersonParam*) { 
    val stringParams = Map(params collect { case parm: TupleParam => parm.tuple }: _*) 
    val mapParams = Map(params collect { case parm: MapParam => parm.map }: _*) 
    val children = params collect { case parm: StringParam => parm.string } toList 
} 

用法:

scala> val bob = new Person("name" -> "Bob", 
    | "pets" -> Map("cat" -> "Mittens", "dog" -> "Spot"), 
    | "status" -> "asleep", 
    | "little bob", "little ann") 
bob: Person = [email protected] 

scala> bob.stringParams 
res11: scala.collection.immutable.Map[String,String] = Map((name,Bob), (status,asleep)) 

scala> bob.mapParams 
res12: scala.collection.immutable.Map[String,Map[String,String]] = Map((pets,Map(cat -> Mittens, dog -> Spot))) 

scala> bob.children 
res13: List[String] = List(little bob, little ann) 
相關問題