当伴生对象在类中时使用.tupled方法

44

我正在从Slick迁移到Slick 2,而在Slick 2中,当投影到一个case类(如此处所示http://slick.typesafe.com/doc/2.0.0-RC1/migration.html)时,你应该使用tupled方法。

问题在于如果case类有伴生对象,例如像这样:

case class Person(firstName:String, lastName:String) {

}

与伴生对象一起使用

object Person {
  def something = "rawr"
}
在相同的作用域中,tupled 方法不再起作用,因为它试图在 object 上运行 tupled,而不是在case class上运行。
有没有一种方法可以检索出 Personcase class 而不是 object,以便您可以正确地调用 tupled

就像我之前所说的,你可以把辅助函数放在任何对象中,并将它们导入到Person中;它不一定要是伴生对象。 - Erik Kaplun
1
是的,但惯用语来说,如果您有处理“人员”(Person)的全局函数,则应该在“Person”命名空间上运行它们,这就是单例模式的全部目的。当我们使用 BigDecimal(例如)时,如果有全局方法,则应将这些方法附加到 BigDecimal 而不是 BigDecimalHelpers 或类似的其他名称,这是有原因的。 - mdedetrich
使用与其case class相同命名空间的对象的意图并不是为了覆盖case class,而是将object中的方法/值添加到case class的相同命名空间中。这种做法在几乎所有主流的面向对象编程语言(包括Java、Scala等)中都有应用。除非您在object中定义了applyunapply,否则您不会重写或重新实现case classes,而是在命名空间上进行添加。无论一个classcase class还是普通class都是无关紧要的,case classes只是添加了apply/unapply方法。 - mdedetrich
好的,我明白了,但是为什么tupled方法消失了呢? - Erik Kaplun
3
实际上它们并没有消失,请看这个回答 https://dev59.com/e2Eh5IYBdhLWcg3wdzaR#22368413。至于为什么 tupled 方法会 "消失",我不知道。经过一些快速的阅读,可能是由于隐式转换将其引入作用域的方式(这是在内部完成的)。请记住,即使有伴生 object,您仍然可以很好地使用 case classes。这个问题只是因为我特别需要使用 tupled 方法而出现的。 - mdedetrich
显示剩余7条评论
4个回答

87

你也可以写

(Person.apply _).tupled
为避免重复类型。

1
如果伴生对象具有自己的apply方法(一个重载的构造函数),那该怎么办?编译器无法解析apply方法... - AHonarmand
1
找到答案了:https://dev59.com/Op3ha4cB1Zd3GeqPT2iI - AHonarmand
无法编译:找不到“apply”。 - WestCoastProjects
@javadba 是的,就是这个链接:https://scalafiddle.io/sf/a5rsgke/0。你确定你有一个 case class 吗? - Alexey Romanov

25

这与Alexey Romanov所说的非常相似,但为了避免每次需要tupled时都要使用apply,我们只需将其添加到我们的伴生对象中。

object Person {
  def something = "rawr"
  def tupled = (Person.apply _).tupled
}

现在你可以像没有伴生对象一样调用Person.tupled


7

谢谢,那真的有效(我想这里没有任何绕过(String,String)样板的方法)。 - mdedetrich

4
为了进一步完善其他评论,您还可以执行以下操作,因为元组正在调用案例类的生成默认应用程序方法。
object Person {
  ...
  def tupled = (this.apply _).tupled
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接