scala - Scala 中的模式匹配与案例类

标签 scala pattern-matching case-class

我正在为远程存储设计一个模型,结果是:

sealed trait StorageTag
case object Gcs extends StorageTag
case object S3 extends StorageTag

sealed trait StorageFile[T <: StorageTag]
final case class GcsFile(bucket: String, path: String) extends StorageFile[Gcs.type]
final case class S3File(bucket: String, path: String) extends StorageFile[S3.type]

sealed trait StorageConfig[T <: StorageTag]
final case class GcsConfig(keyPath: String) extends StorageConfig[Gcs.type]
final case class S3Config(keyPath: String) extends StorageConfig[S3.type]

def open[T <: StorageTag](storageFile: StorageFile[T], storageConfig: StorageConfig[T]): OutputStream =
  (storageFile, storageConfig) match {
    case (f: S3File, c: S3Config) => //
    case (f: GcsFile, c: GcsConfig) => //
  }

但是 Scala 编译器提示以下警告:
Warning:(39, 5) match may not be exhaustive.
It would fail on the following inputs: (GcsFile(_, _), S3Config(_)), (S3File(_, _), GcsConfig(_))
    (storageFile, storageConfig) match {

但在我的具体情况下,用 S3File 打开 GcsConfig 显然是没有意义的,反之亦然。有没有办法增强模型?

我个人不喜欢在那些不真实的情况下抛出异常或将其保留为 MatchError 的想法,例如 GcsFileS3Config

最佳答案

您需要向编译器提供一些关于允许哪些对的信息。通过将 storageFile: StorageFile[T], storageConfig: StorageConfig[T] 对传递给 open 方法,您总是面临有人使用错误的标准调用 open 方法的风险,您将不得不处理异常(exception)情况。为了使其以类型安全的方式工作,您需要传递“知道”允许哪些对的预定义类型。

例如像这样:

sealed trait StorageTag
case object Gcs extends StorageTag
case object S3 extends StorageTag

sealed trait StorageFile[T <: StorageTag]
final case class GcsFile(bucket: String, path: String) extends StorageFile[Gcs.type]
final case class S3File(bucket: String, path: String) extends StorageFile[S3.type]

sealed trait StorageConfig[T <: StorageTag]
final case class GcsConfig(keyPath: String) extends StorageConfig[Gcs.type]
final case class S3Config(keyPath: String) extends StorageConfig[S3.type]

sealed trait FileConfPair
case class S3Conf(f: S3File, c: S3Config) extends FileConfPair
case class ScsConf(f: GcsFile, c: GcsConfig) extends FileConfPair

def open[T <: StorageTag](fp: FileConfPair): OutputStream =
  fp match {
    case S3Conf(f: S3File, c: S3Config) => ???
    case ScsConf(f: GcsFile, c: GcsConfig) => ???
  }

关于scala - Scala 中的模式匹配与案例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53680684/

相关文章:

scala - 用Scala中的另一个特征继承自类型特征

scala - 折叠具有未知类型的 HList

scala - 如何在 Simple Build Tool 的子项目中共享我的 lib 文件夹

scala - 为什么在这种情况下需要过滤器实现?

pattern-matching - 在 Racket 中进行模式匹配时的替代方案

functional-programming - Rust 中模式的定义是什么,什么是模式匹配?

scala - 为什么以及如何将案例类迁移到 Scala 中的提取器

scala - 如何使用@RunWith(classOf [JUnitRunner])升级到Scala测试的JUnit5?

scala - 尝试使用类型参数编写 DRY Scala 代码

使用 Scala 的案例类模式中的正则表达式模式