又一个难以捉摸的非详尽的比赛

时间:2015-04-11 09:45:39

标签: scala scalac

我收到以下匹配警告。

" 匹配可能并非详尽无遗。它会在以下输入上失败:一些((x:抽象forSome x不在(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不是一个非常动态的语言,那么为什么编译器不知道编译警告中提到的组是空组?

1 个答案:

答案 0 :(得分: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对象执行逻辑的更好(且更易于维护/可扩展)的方法是使用类型类。

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)
    }
}

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

相关问题