首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为模式匹配定义`StrContains.unapply`?

如何为模式匹配定义`StrContains.unapply`?
EN

Stack Overflow用户
提问于 2015-08-10 15:36:26
回答 1查看 79关注 0票数 0

在我的代码中有一个方法,它需要检查传递的字符串是否包含一些指定的字符,然后执行一些操作。

代码看起来是:

代码语言:javascript
复制
def check(str: String) = {
  if(str.contains("A")) {
    doSomething()
  } else if(str.contains("B")) {
    doSomething()
  } else if(str.contains("C")) {
    doSomething()
  } else {
    doSomething()
  }
}

我想试一试模式匹配,但不太满意:

代码语言:javascript
复制
def check(str: String) = str match {
  case s if s.contains("A") => doSomething()
  case s if s.contains("B") => doSomething()
  case s if s.contains("C") => doSomething()
  case _ => doSomething()
}

我希望我可以定义一个StrContains.unapply来像这样使用它:

代码语言:javascript
复制
def check(str: String) = str match {
  case StrContains("A") => doSomething()
  case StrContains("B") => doSomething()
  case StrContains("C") => doSomething()
  case _ => doSomething()
}

但现在可以确定该怎么做了。有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-10 16:39:05

问题是,当您执行case StrContains("A")时,编译器将首先调用StrContains.unapply/unapplySeq (无论以何种方式定义),然后尝试将返回的结果与"A"匹配。"A"文本本身永远不会传递给StrContains.unapply/unapplySeq,因此它无法在unapply/unapplySeq中执行调用s.contains("A")

简单地说,这意味着您需要定义不同的对象,比如StrContainsA/StrContainsB/StrContainsC,这显然比简单地执行case s if s.contains("A")更糟糕。

但是,有一种替代的(而且有些人为的)解决方案,它允许定义单个提取器,同时仍然能够指定要匹配的子字符串内联,这就是利用scala支持基于字符串内插定义提取器的事实:

代码语言:javascript
复制
implicit class ContainsContext (val sc : StringContext) {
  object StrContains {
    def unapply(str: String): Boolean = {
      val substr: String = sc.parts.mkString
      str.contains(substr)
    }
  }
}

用法:

代码语言:javascript
复制
def check(str: String) = str match {
  case StrContains"A" => doSomething()
  case StrContains"B" => doSomething()
  case StrContains"C" => doSomething()
  case _ => doSomething()
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31923678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档