これはおそらく理想的ではありませんが、Abstract を封印したくない場合には機能します。
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)
}
}
型クラスを使用すると、徹底的なパターン マッチングが得られ、ライブラリのユーザーが独自の Abstract を実装する場合、PerformAction を実装する必要があるため、ライブラリの外部で型の安全性が得られます。