Scala中的模式匹配与案例类

Som*_*ame 4 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) => //
  }
Run Code Online (Sandbox Code Playgroud)

但Scala编译器抱怨以下警告:

Warning:(39, 5) match may not be exhaustive.
It would fail on the following inputs: (GcsFile(_, _), S3Config(_)), (S3File(_, _), GcsConfig(_))
    (storageFile, storageConfig) match {
Run Code Online (Sandbox Code Playgroud)

但是,在我的具体情况下,这显然是一个无感打开S3FileGcsConfig反之亦然.有没有办法增强模型?

我个人不喜欢抛出异常或把它当作的想法MatchError在那些不真实的情况下,像GcsFile使用S3Config.

Bog*_*nko 8

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

例如这样:

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) => ???
  }
Run Code Online (Sandbox Code Playgroud)