首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于unapply方法在Scala中如何工作的说明

关于unapply方法在Scala中如何工作的说明
EN

Stack Overflow用户
提问于 2017-10-24 03:59:27
回答 2查看 633关注 0票数 0

我对流程的理解正确吗?考虑下面的代码

代码语言:javascript
复制
class Employee(val firstName: String, val middleName: Option[String], val lastName: String)

object Tokenizer {
  def unapply(x: Employee) = Some(x.firstName, x.lastName)
}

val e = new Employee("Kurt", None, "Vonnegut") 
val result = e match {
  case Tokenizer(c, d) ⇒ "c: %s, d: %s".format(c, d)
  case _ ⇒ "Not found"
}

e将被传递给Tokenizer.unapply(x:Employee)Some()的结果被赋值给(c,d),我说的对吗?从代码的外观看,我们似乎在调用Tokenizer(c,d),但没有使用类似于Tokenizer(c,d)的签名定义applyunapply方法

EN

回答 2

Stack Overflow用户

发布于 2017-10-24 04:54:14

是的,你理解得没错。unapply可能有点让人费解,因为当您在case中看到它时,您编写的是它的返回类型,而不是参数类型。Tokenizer.unapply的签名是Employee => Some[(String, String)]。与case Tokenizer(c, d)对应的部分是返回类型。

然而,我有几个(非常小的)nit要挑选。您应该为所有的公共方法指定类型,因为您最终可能会推断出过于具体的类型(它在这里通过推断Some而不是Option来显示),然后更改您的代码(在本例中,可能会使它变得可能会因为None而失败)更改它的接口。但是,如果您希望不会更改Tokenizer使其失败,那么就不需要通过返回Option来招致装箱惩罚。相反,您可以这样做

代码语言:javascript
复制
// Don't worry if you don't understand this yet. You can ignore this trick and come back to it much later
// Also: I think this only works on Scala 2.12
final case class Box[+T](t: T) extends AnyVal {
  def isEmpty = false
  def get = t
}
object Tokenizer {
  def unapply(e: Employee): Box[(String, String)] = Box((e.firstName, e.lastName))
}
// Incurs no boxing penalty, but now you can't change it to allow failure without changing the interface

最后的nit:调用一个需要没有双括号的元组的函数是一种糟糕的风格。不要写Some(a, b);要写Some((a, b))。它有点难看,但第一个可能是模棱两可的,那就更糟了。

票数 2
EN

Stack Overflow用户

发布于 2017-10-24 04:47:56

具有unapply方法的对象是提取器对象。它通过提取传递给apply的各个值来执行与apply方法相反的操作。因此,在上面的示例中,result将包含元组("Kurt", "Vonnegut")

注意,您也可以在这里使用赋值而不是模式匹配:

代码语言:javascript
复制
$ val Tokenizer(emp) = e
emp: (String, String) = ("Kurt", "Vonnegut")    
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46897529

复制
相关文章

相似问题

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