如何在另一个构造函数中获得类似Map的糖

时间:2011-01-06 01:32:09

标签: scala

需要是一个类XI可以构造一个Map,它将字符串带入其他字符串或映射,将字符串转换为字符串,然后是任意数量的其他X实例。对Scala的掌握有限,我知道我可以这样做:

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

但是看起来不是很Scala-ish(“Scalish”?“Scalerific”?“Scalogical”?)我希望能够做到以下几点:

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

我知道我可以通过使用伴侣对象摆脱“新”,我相信我可以看看Scala varargs。我想知道的是:

  1. 我如何使用 - > (或一些类似合理的算子)构造要在建筑中制作成地图的元素?
  2. 如何定义单个地图,以便它可以在两个非常不同的类型之间执行类似Option的切换,或者成为递归树,其中每个(命名)节点指向String或其他形式的叶子节点喜欢自己吗?
  3. 递归版本真的很吸引我,因为虽然它没有解决我今天实际遇到的问题,但它整齐地映射到只包含对象和字符串(没有数字或数组)的JSON子集。

    任何帮助,一如既往,非常感谢。

3 个答案:

答案 0 :(得分:3)

->只是制作一对(A, B)的语法糖,所以你也可以使用它。 Map object需要一对vararg:

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

如果您对模仿馆藏图书馆感兴趣,请先查看The Architecture of Scala Collections

话虽如此,我认为您为Person建议的签名看起来不像Map,因为它需要变量参数,但children与其他(String, A)不一致"child1" -> Alice 1}}主题。如果您单独说Alice并在内部存储def apply(elems: (String, Any)*): Person ,则可以定义:

Any

在伴侣对象中。如果PersonElem过于宽松,您可以定义def apply(elems: (String, PersonElem)*): Person 特征

String

以及Map[String, String]PersonPersonElem等与{{1}}之间的隐式转换。

答案 1 :(得分:1)

这让你几乎到了那里。还有一张我不容易摆脱的地图。

基本方法是使用一种有点人为的参数类型,它继承自普通类型。这样,apply方法只需要一个vararg。

使用隐式转换方法我摆脱了参数类型

的丑陋构造函数
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)
    } }

答案 2 :(得分:0)