0

我收到以下匹配警告。

match 可能并不详尽。它会在以下输入上失败: Some((x: Abstract forSome x not in (A, B, C)))

代码:

abstract class Abstract
case class A() extends Abstract
case class B() extends Abstract
case class C() extends Abstract

class matcher {
  def matcher(a: Option[Abstract]) = a match {
    case None      => true  
    case Some(A()) => false 
    case Some(B()) => false 
    case Some(C()) => false 
  }
}

如果您想知道,这里的案例类没有参数,但在我的真实代码中它们有。Abstract我希望答案不是“编译器无法知道程序中某处是否还有其他子类......

使抽象类密封是唯一的解决方案吗?scala 不是一个很动态的语言,那么编译器怎么不知道编译警告中提到的组是一个空组呢?

4

1 回答 1

1

这可能并不理想,但如果您不想密封摘要,它会起作用。

abstract class Abstract
sealed abstract class SealedAbstract
case class A() extends SealedAbstract
case class B() extends SealedAbstract
case class C() extends SealedAbstract

class matcher {
    def matcher(a: Option[Abstract]) = a match {
        case None => true  
        case Some(thing) => matcher(thing)
    }
    def matcher(a: Abstract) = a match{
        case seal: SealedAbstract => matcher(seal)
        case _ => false
    }
    //this will be exhaustive
    def matcher(a: SealedAbstract) a match{
        case A() => false
        case B() => false
        case C() => false
    }
}

针对抽象对象执行逻辑的更好(并且更可维护/可扩展)的方法是使用类型类。

abstract class Abstract
sealed abstract class SealedAbstract
case class A() extends SealedAbstract
case class B() extends SealedAbstract
case class C() extends SealedAbstract

trait PerformAction[Type <: Abstract]{def doSomething(in: Type): String}
implicit object SealedPerformAction extends PerformAction[SealedAbstract]{
    override def doSomething(sa: SealedAbstract): String = "It does."
}

class matcher {
    def doIfExists[Type <: Abstract](a: Option[Type])(implicit ev: PerformAction[Type]): String = a match{
        case None => ""
        case Some(thing) => ev.doSomething(thing)
    }
}

使用类型类,您可以获得详尽的模式匹配,并且您可以在库之外获得类型安全,因为如果您的库的任何用户实现了自己的 Abstract,则她必须实现 PerformAction。

于 2015-04-12T14:30:09.480 回答