Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Scala中延迟类值的赋值?_Scala_Oop - Fatal编程技术网

如何在Scala中延迟类值的赋值?

如何在Scala中延迟类值的赋值?,scala,oop,Scala,Oop,我有一个类,它是使用从.conf文件读取的数据a创建的。该类还包含一个不是来自conf文件的值b 班级: case class Configuration(a: String, b: String) 实例化配置的调用顺序如下所示: 用户->ConfigurationCompiler->ConfigurationReader->readConfig():配置 (用户返回一个配置对象) 值a由.conf文件读取和设置,但值b由用户指定。我不想将值b一直传递到readConfig(),以便在实例化配

我有一个类,它是使用从.conf文件读取的数据
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)
就足够了。