Scala代数数据类型,用于格式化映射的文件扩展名

时间:2014-01-13 19:10:09

标签: scala case-class algebraic-data-types

所以我是一个Scala noob,来自生锈的Java背景和主要的PHP + JavaScript。 我发现自己感到沮丧,因为我想在Scala中实现设计模式,但我不知道如何导致大量阅读,而且从不进行任何编程。

无论如何所以我正在忙着制作一个基本程序来学习细节,我正在制作一个配置文件阅读器。我需要做的是将不同的格式映射到扩展,诀窍是不同的扩展名(例如yamlyml)映射到相同的格式。

在java中,我会使用Enums并控制构造函数中的映射。挺直的。

scala ......不是那么多。首先,我发现ADT(意思是代数数据类型而非抽象数据类型)是使用Enumeration的更好的选择(原因对我来说仍然不清楚),并且它对Java库更有效(具有讽刺意味的是,我没有想法为什么。)

接下来我发现ADT的各种格式,作为一个初学者同时掌握所有概念是艰苦的。我已经设法找出companion Objects类似于javascript,因为它是一个单独的实例化,几乎像一个单例,并允许您在静态上下文中访问已定义的函数。


现在回到问题

我写过我认为是个好主意但是代码看起来很麻烦,冗长,我无法弄清楚一些用例,而且从我所有的JS插件中看起来我有点像namespacing nut在逻辑分离方面表现良好,但在scala中表现不够简洁。

class ConfigManager {
  object Formats{
    case class Format(f: String){
      val format = f.toUpperCase()
    }
    case object Yaml extends Format("YAML")
    case object Xml  extends Format("XML")
    case object Json extends Format("JSON")
  }

  object Extensions {
    case class Extension(e: String) {
      val extension = e.toUpperCase()
    }
    case object Yaml extends Extension("YAML")
    case object Yml  extends Extension("YML")
    case object Xml  extends Extension("XML")
    case object Json extends Extension("JSON")
  }


  object Config {
    private sealed trait ConfigFormats {
      def f: Formats.Format
      def e : Extensions.Extension
    }
    case class ConfigFormat(f: Formats.Format, e: Extensions.Extension) 
            extends ConfigFormats (f, e)

    case object Yaml1 extends ConfigFormat(Formats.Yaml, Extensions.Yaml)
    case object Yaml2 extends ConfigFormat(Formats.Yaml, Extensions.Yml)
    case object Xml   extends ConfigFormat(Formats.Xml, Extensions.Xml)
    case object Json  extends ConfigFormat(Formats.Json, Extensions.Json)
  }

  //this looks nice, and useful, is concise and does what I want
  def readConfig(c: Config.ConfigFormat){
    c.f match {
      case Formats.Yaml => readConfigYaml()
      case Formats.Json => readConfigJson()
      case Formats.Xml  => readConfigXml()
      case _ => throw new Exception("Invalid Config format")
    }
  }

  //and this is where I lose the plot
  def setFormat(extension: String){
    val configFormat = new Extensions.Extension(discoveredFormat) match {
      case Config.????? => ????
    }
  }
}

所以显而易见的问题是我的实施有多糟糕,我应该做些什么,为什么? (我最关心的是“为什么”)

1 个答案:

答案 0 :(得分:1)

Scala枚举很好,您可以像这样定义FormatsExtensions

object Formats extends Enumeration {
  type Eny = Value
  val YAML, XML, JSON = Value
}
object Extensions extends Enumeration {
  type Eny = Value
  val YAML, YML, XML, JSON = Value
}

如果您想要地图,只需使用地图

val configFormats: Map[Extensions.Value, Formats.Value] = Map(
  Extensions.YAML -> Formats.YAML,
  Extensions.YML  -> Formats.YAML,
  Extensions.XML  -> Formats.XML,
  Extensions.JSON -> Formats.JSON)

然后我不确定你的方法应该做什么,但看起来你的setFormat可以这样开始:

def setFormat(extension: String): Unit = {
  val format: Formats.Value = configFormats(Extensions withName extension)
  ...
}

你看,就像Java :)如果你更好地描述你想做什么,我们可能会给你一个更“习惯的方式”。