Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何公开模式匹配的测试_Scala - Fatal编程技术网

Scala 如何公开模式匹配的测试

Scala 如何公开模式匹配的测试,scala,Scala,我是scala的新手,但基本上已经找到了自己的方法 在这里,我想问一下实现这一点的推荐/最佳实践/惯用方法: 在内部,MyClass使用一个状态类型,它由案例类的密封层次结构实现 但是在API上,只应该公开一些布尔谓词,通过匹配(内部)状态来实现 目前,我的实现是沿着 def isSane: Boolean = state match { case Ok(_,'valid) => true case _ => false } 但是这个解决方

我是scala的新手,但基本上已经找到了自己的方法

在这里,我想问一下实现这一点的推荐/最佳实践/惯用方法:

  • 在内部,MyClass使用一个状态类型,它由案例类的密封层次结构实现
  • 但是在API上,只应该公开一些布尔谓词,通过匹配(内部)状态来实现
目前,我的实现是沿着

def isSane: Boolean = state match {
    case Ok(_,'valid) => true
    case _            => false
}
但是这个解决方案让我觉得很尴尬,好像用3行代码来表达某个东西,它的信息内容只相当于一行代码。实际上,我想写的是:

def isSane: boolean = state matches Ok(_, 'valid)

很可能在scala中自己实现一个合适的操作符是可能的,但是在我研究这个之前,我想知道解决这个问题的通常方法是什么。如果静态地知道
符号
属性是
状态
类型的属性,那么可能还有一些现有的库实现:

def isSane: Boolean =
  state.secondSymbolPropertyWhateverItsCalled == 'valid
如果您不知道
状态
正常
,则:

def isSane: Boolean =
  state.isInstanceOf[Ok] && state.asInstanceOf[Ok].symbolProp == 'valid
但在这一点上,它并不比你写的更好

最后,您可以在该类型层次结构上定义
isSane
,并委托给它:

def isSane: Boolean =
  state.isSane

我可能很守旧,但为什么不使用多态性呢

trait State { def sane: Boolean }

trait InvalidState extends State { def sane = false }

case class Ok(whatever: Whatever, s: Symbol) extends State {
   def sane = { s == 'valid }
}

case class Failure(msg: String) extends InvalidState 

case class WarmingUp extends InvalidState

// ...

def isSane(): Boolean = state.sane
当然,如果出于任何原因都不可能,您可以概括如下:

class Matcher[T](o: T) {
   def matches(pf: PartialFunction[T, Unit]) = pf isDefinedAt o
}

object Matcher {
   implicit def o2matcher[T](o: T): Matcher[T] = new Matcher(o)
}

// then
def isSane = state matches { case Ok(_,'valid) => }

我会这样做:

abstract class State {
  def matches(pf: PartialFunction[State, Unit]) = pf isDefinedAt this
}

// then

def isSane = state matches { case Ok(_,'valid) => }

因为
matches
被定义为接收部分函数,所以您可以在函数后面加上一个函数文本,其中只包含应该导致true的case语句。您不需要返回任何内容,因为分部函数定义为返回
Unit
。最后,
matches
方法使用部分函数的
isDefinedAt
方法来验证是否有一个case语句覆盖了它本身。

在我看来,
State
不是调用
sane
的类,只是一个内部使用的类。一旦检查变得更加复杂,我会选择经典的OO风格的解决方案。我不认为这是过时的,只是我的可读性是标准。也就是说,如果基于模式匹配的解决方案可以写在一行中,并且以一种能够立即传达我意图的方式,那么我更喜欢它,而不是经典的方法。是的,事实上,这就是我的想法,以防有必要自己实现它……在我想到的示例中,关键是要在一个可能的状态下匹配某个属性。。。另一个有趣的问题是关于性能……我的猜测是,编译器实际上从原始模式匹配生成了类似于第二个示例的内容,而OTOH,将isSane放入状态层次结构将允许交换一些额外的存储以获得可能改进的性能。但无论如何,考虑到当今系统的性能,在大多数情况下,这样细微的差异并不重要