【发布时间】:2014-01-14 16:29:38
【问题描述】:
所以我是一个完全的 Scala 菜鸟,来自生疏的 Java 背景和主要是 PHP+JavaScript 的背景。 我发现自己很沮丧,因为我想在 Scala 中实现一些设计模式,但我不知道如何实现,这会导致大量阅读,而不是任何编程。
不管怎样,我正忙着制作一个基本程序来学习细节,我正在制作一个配置文件阅读器。我需要做的是将不同的格式映射到扩展,诀窍是不同的扩展,如yaml 和yml 映射到相同的格式。
在 java 中,我将使用 Enums 并控制构造函数中的映射。很直接。
在 scala 中...不是那么多。首先,我发现 ADT(意思是代数数据类型而不是抽象数据类型)是比使用枚举更好的选择(原因我仍然不清楚),并且它与 Java 库一起工作得更好(具有讽刺意味的是,我没有知道为什么。)
接下来我发现了 ADT 的各种格式,作为初学者同时掌握所有概念是很费力的。我已经设法弄清楚companion Objects 类似于 javascript,因为它是一个几乎像单例的单个实例化,并且允许您在静态上下文中访问定义的函数。
现在回到问题
我写了我认为是个好主意的东西,但是代码看起来很麻烦,冗长,而且我无法弄清楚一些用例,而且从我所有的 JS 插件编写中可以看出我有点命名空间螺母,在逻辑分离方面做得很好,但在 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.????? => ????
}
}
}
所以显而易见的问题是我的实现到底有多糟糕,我应该怎么做,为什么? (我最关心的是“为什么”)
【问题讨论】:
-
你应该使用包而不是对象。然后使用多态性。也许你不需要这么多类型来实现你的目标。
-
如果你想保持功能,试着让你的方法返回一个值而不是产生副作用。
-
许多设计模式在 Scala 中没有用,因为它们解决的问题已经消失了。
-
所以我已经意识到,但这并不意味着scala中的“正确”方式自然而然。说到这一点,我仍然很想知道 ADT 的实现,以及为什么。
标签: scala case-class algebraic-data-types