【发布时间】:2014-04-24 07:04:36
【问题描述】:
我最近一直在研究基于 Apache POI 功能的 DSL 样式库包装器,并面临一个我似乎无法很好解决的挑战。
该库的目标之一是为用户提供将电子表格模型构建为不可变对象集合的能力,即
val headerStyle = CellStyle(fillPattern = CellFill.Solid, fillForegroundColor = Color.AquaMarine, font = Font(bold = true))
val italicStyle = CellStyle(font = Font(italic = true))
有以下假设:
- 用户可以选择指定任何参数(也就是说,您可以创建不带参数的
CellStyle以及明确指定参数的完整列表); - 如果用户未明确指定参数,则将其视为未定义并使用默认环境值(我们要转换为的格式的默认值);
第二点很重要,因为我想将此数据模型转换为多种格式,即 Excel 中的默认字体不必与 HTML 浏览器中的默认字体相同(如果用户未定义明确的字体系列我希望他使用这些默认值查看数据)。
为了满足要求,我使用了此处描述的空模式的变体:Pattern for optional-parameters in Scala using null 并在此处建议Scala default parameters and null(下面是一个简化示例)。
object ModelObject {
def apply(modelParam : String = null) : ModelObject = ModelObject(
modelParam = Option(modelParam)
)
}
case class ModelObject private(modelParam : Option[String])
由于 null 仅在伴生对象内部使用并且非常本地化,为了解决方案的简单性,我决定接受 null 牺牲。该模式适用于所有参考类。
但是对于 Scala 原始类型包装器,不能指定 null。对于布尔值来说,这尤其是一个巨大的问题,我有效地考虑了 3 种状态(真、假和未定义)。想要提供接口,用户仍然可以编写bold = true,我决定使用接受空值的 Java 包装器。
object ModelObject {
def apply(boolParam : java.lang.Boolean = null) : ModelObject = ModelObject(
boolParam = Option(boolParam).map(_.booleanValue)
)
}
case class ModelObject private(boolParam : Option[Boolean])
但这并不正确,我一直想知道是否有更好的方法来解决这个问题。我一直在考虑定义联合类型(带有表示未定义值的附加对象):How to define "type disjunction" (union types)?,但是由于不应该明确使用未定义状态,IDE 向用户公开的参数类型,它将非常令人困惑(理想情况下,我希望它是布尔值)。
有没有更好的方法来解决这个问题?
更多信息:
【问题讨论】:
标签: scala