在 Scala 中公开私有案例 class

Expose private case class in Scala

我有一种情况,代码路径被赋予一些 Path 用于查询数据库。碰巧 有时 其中一些路径需要通过翻译服务,以便在查询之前将它们映射到更新的 Paths。本质上简化的流程是

val paths: List[Path] = getPaths()

val pathTranslationOpt: Option[Map[Path, Path]] = getTranslationOpt()

paths.foreach { p =>
  val pathToUse = 
    pathTranslationOpt
      .flatMap(_.get(p))
      .getOrElse(p)

  someFunctionsUsingThePath(pathToUse)
}

我担心有人不小心用 p 调用 someFunctionsUsingThePath,忘记执行翻译的情况。这可能会在编译时被捕获,稍微修改代码

val paths: List[Path] = getPaths()
 // let NewPath be a case class defined in the scope of the translate function as 
// case class NewPath(path: Path)
val pathTranslationOpt: Option[Map[Path, NewPath]] = getTranslationOpt()

paths.foreach { p =>
  // Have the function explicitely take a NewPath so the user cannot forget to call the translation service
  someFunctionsUsingThePath(
    newPathOpt = 
      pathTranslationOpt.flatMap(_.get(p)),
    fallbackPath = p
  )
}

这对我来说似乎更安全,因为忘记调用翻译服务会导致编译时错误。然而,粗心的用户可能会简单地将 Some(NewPath(p)) 传递给函数调用,从而破坏了目的。

有没有办法让 NewPath 可以自由使用,但只能从翻译调用构建?

试试这个:

case class NewPath private(path: Path)

object NewPath {
  def apply(path: Path): NewPath =
    NewPath(
      pathTranslationOpt.flatMap(_.get(path)).getOrElse(path)
    )
}

def someFunctionsUsingThePath(path: NewPath) = ???

paths.foreach { p =>
  someFunctionsUsingThePath(NewPath(p))
}

NewPath 只能通过伴随对象中的 apply 方法创建,该方法在必要时转换路径,否则保持不变。