Scala“多级”抽象类/抽象对象替换

时间:2014-12-29 14:30:25

标签: scala inheritance

我使用非常方便的Scala对象结构来捕获我的设置,如下面的

object Settings {
    object ObjectSever {
       val URL = "http://localhost:8081"
       val timeout = 20
    }
    object ConnectionPools {
       object Limits {
          val timeout = 10
          val max = 5
          val prefix = "pref_"
       }
    }
} 

然而,我来到了需要具有以下结构的多个实例的地步,用于测试,不同的配置提供程序等。 所以我尝试用这种结构构建一个抽象类,但是我失败了。 我可以轻松地用Settings替换abstract class,但是如何重现这种漂亮的嵌套结构? 我还想保持编译类型的安全性 - 当我错过子类中的某些元素时会出错。

2 个答案:

答案 0 :(得分:4)

我认为这里不需要抽象类,因为你似乎只想要一个没有任何实际继承的不可变数据结构。嵌套的案例类应该没问题。

case class Settings(server: ObjectServer, connectionPools: ConnectionPools)
case class ObjectServer(URL: String, timeout: Int)
case class ConnectionPools(limits: Limits)
case class Limits(timeout: Int, max: Int, prefix: String)

val settings = Settings(
    ObjectServer(
        URL = "http://localhost:8081",
        timeout = 20
    ),
    ConnectionPools(
        Limits(
            timeout = 10,
            max = 5,
            prefix = "pref_"
        )
    )
)

对于它的价值,这是使用抽象类和这些类的匿名实例化的一种方法:

abstract class Settings {
    val server: ObjectServer
    val connectionPools: ConnectionPools
}

abstract class ObjectServer {
    val URL: String
    val timeout: Int
}

abstract class ConnectionPools {
    val limits: Limits
}

abstract class Limits {
    val timeout: Int
    val max: Int
    val prefix: String
}

object MySettings extends Settings {
    val server = new ObjectServer {
       val URL = "http://localhost:8081"
       val timeout = 20
    }

    val connectionPools = new ConnectionPools {
        val limits = new Limits {
            val timeout = 10
            val max = 5
            val prefix = "pref_"
        }
    }
 }

答案 1 :(得分:1)

您可以按如下方式使用案例类:

case class ObjectSever(URL: String = "http://localhost:8081", timeout: Int = 20)
case class Limits(timeout: Int = 10, max: Int = 5, prefix: String = "pref_")
case class ConnectionPools(limits: Limits = Limits())
case class Settings(
    server: ObjectSever = ObjectSever(), 
    pools: ConnectionPools = ConnectionPools())

val setts1 = Settings()
// Settings(
//  ObjectSever(http://localhost:8081,20),
//  ConnectionPools(Limits(10,5,pref_)))

val setts2 = setts1.copy(
  server = setts1.server.copy(URL = "http://stackoverflow.com"),
  pools = setts1.pools.copy(limits = setts1.pools.limits.copy(timeout = 100)))
// Settings(
//  ObjectSever(http://stackoverflow.com,20),
//  ConnectionPools(Limits(100,5,pref_)))

val setts3 = Settings(ObjectSever("http://localhost"))
// Settings(
//  ObjectSever(http://localhost,20),
//  ConnectionPools(Limits(10,5,pref_)))