如何在Scala中延迟类值的赋值?
我有一个类,它是使用从.conf文件读取的数据如何在Scala中延迟类值的赋值?,scala,oop,Scala,Oop,我有一个类,它是使用从.conf文件读取的数据a创建的。该类还包含一个不是来自conf文件的值b 班级: case class Configuration(a: String, b: String) 实例化配置的调用顺序如下所示: 用户->ConfigurationCompiler->ConfigurationReader->readConfig():配置 (用户返回一个配置对象) 值a由.conf文件读取和设置,但值b由用户指定。我不想将值b一直传递到readConfig(),以便在实例化配
a
创建的。该类还包含一个不是来自conf文件的值b
班级:
case class Configuration(a: String, b: String)
实例化配置的调用顺序如下所示:
用户->ConfigurationCompiler
->ConfigurationReader
->readConfig():配置
(用户返回一个配置对象)
值a
由.conf文件读取和设置,但值b
由用户指定。我不想将值b
一直传递到readConfig(),以便在实例化配置时设置它
我曾经尝试过选项
,但对我来说它看起来很难看,因为您首先用无
实例化b
,然后再设置它。此外,这些测试看起来很奇怪,因为您必须测试Some(String)
,而不是String
。选项似乎也不适合这里,因为该字段实际上不是可选的,只是在以后设置
选项
类:
case class Configuration(a: String, var b: Option[String])
一些解决方案可能是使用隐式
,但是隐式字符串
看起来不太好-隐式类型是按类型解析的,因此它应该比字符串
更不一般
我能想到的是readConfig()
返回的PartialConfiguration
。然后,您可以将其值添加到用户提供的值中,以创建完整的配置您可以在b
位置使用默认值创建原始配置对象。当您获得b
的实际值时,请使用以下方法创建一个供您的程序使用的副本:
val realConfig = originalConfig.copy( b = bValue )
副本将用实际使用的所需值替换字段b
。我会选择生成器。下面是一个例子:
import cats.implicits._
import cats.data.ValidatedNel
case class ConfigBuilder(a: Option[String] = None, b: Option[String] = None) {
def withA(a: String): ConfigBuilder = copy(a = Some(a))
def withB(b: String): ConfigBuilder = copy(b = Some(b))
def build: ValidatedNel[String, Configuration] =
(a.toValidNel("'a' must be defined"), b.toValidNel("'b' must be defined"))
.mapN(Configuration)
}
正在验证两个字段:
ConfigurationBuilder()
.build
// Invalid(NonEmptyList('a' must be defined, 'b' must be defined))
正在获取有效配置:
ConfigurationBuilder()
.withA("test")
.withB("test2")
.build
// Valid(Configuration(test,test2))
我认为这是一个最简单的解决方案,它不使用默认值,如果您打算稍后设置默认值,那么我觉得这些默认值并不优雅。我喜欢这种方法,因为它会返回一个完整的对象,它被显式地表示为部分配置
,而不是配置
,其中隐含缺少部分。@jcallin您必须能够检查部分配置
对象吗?如果没有,您可以直接使用函数ConfInput=>UserInput=>Configuration
,而无需创建任何新类来保存中间结果。如果以最简单的方式将配置定义为案例类配置(a:String,b:String)
,那么类型的字符串=>配置的函数(confStr:String)=>(userStr:String)=>配置(confStr,userStr)
就足够了。