如何为 case 类创建一个显式伴随对象,它的行为与替换的编译器提供的隐式伴随对象相同? [英] How do I create an explicit companion object for a case class which behaves identically to the replaced compiler provided implicit companion object?

查看:39
本文介绍了如何为 case 类创建一个显式伴随对象,它的行为与替换的编译器提供的隐式伴随对象相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样定义的案例类:

I have a case class defined as such:

case class StreetSecondary(designator: String, value: Option[String])

然后我定义一个显式伴随对象:

I then define an explicit companion object:

object StreetSecondary {
  //empty for now
}

定义显式伴生对象 StreetSecondary 的行为导致编译器生成的隐式伴生对象"丢失;即替换为无法访问编译器生成的版本.例如,tupled 方法在案例类 StreetSecondary 上通过这个隐式伴随对象可用.但是,一旦我定义了显式伴随对象,tupled 方法就会丢失".

The act of defining the explicit companion object StreetSecondary causes the compiler produced "implicit companion object" to be lost; i.e. replaced with no ability to access the compiler produced version. For example, the tupled method is available on case class StreetSecondary via this implicit companion object. However, once I define the explicit companion object, the tupled method is "lost".

那么,我需要对上述 StreetSecondary 显式伴生对象进行定义/添加/更改,以重新获得因替换编译器提供的隐式伴生对象而丢失的所有功能?我想要的不仅仅是恢复 tupled 方法.我希望恢复所有功能(例如,包括提取器/unapply).

So, what do I need to define/add/change to the above StreetSecondary explicit companion object to regain all the functionality lost with the replacement of the compiler provided implicit companion object? And I want more than just the tupled method restored. I want all functionality (for example, including extractor/unapply) restored.

感谢您提供的任何指导/指导.

Thank you for any direction/guidance you can offer.

更新 1

我已经做了足够多的搜索来发现几件事:

I have done enough searching to discover several things:

A) 显式伴随对象必须在其 case 类之前定义(至少在 Eclipse Scala-IDE WorkSheet 中是这种情况,并且代码在 IntelliJ IDE 的 WorkSheet 中不起作用,无论哪个先出现).

A) The explicit companion object must be defined BEFORE its case class (at least that is the case in the Eclipse Scala-IDE WorkSheet, and the code doesn't work in the IntelliJ IDE's WorkSheet regardless of which comes first).

B) 有一个技术技巧可以强制 tupled 工作(谢谢 drstevens):(StreetSecondary.apply _).tupled 虽然这解决了特定的 tupled 方法问题,它仍然没有准确或完整地描述 scala 编译器在隐式伴生对象中提供的内容.

B) There is a technical trick to force tupled to work (thank you drstevens): (StreetSecondary.apply _).tupled While that solves the specific tupled method problem, it still doesn't accurately or completely describe what the scala compiler is providing in the implicit companion object.

C) 最后,可以定义显式伴随对象来扩展一个函数,该函数匹配主构造函数的参数签名并返回 case 类的实例.它看起来像这样:

C) Finally, the explicit companion object can be defined to extend a function which matches the signature of the parameters of the primary constructor and returns an instance of the case class. It looks like this:

object StreetSecondary extends ((String, Option[String]) => StreetSecondary) {
  //empty for now
}

同样,我仍然没有信心准确或完整地描述 Scala 编译器在隐式伴生对象中提供的内容.

Again, I am still not confident accurately or completely describes what the scala compiler is providing in the implicit companion object.

推荐答案

当为 case 类定义显式伴随对象时(从 Scala 2.11 开始),为了完全替换丢失的隐式伴随对象中的编译器提供的功能,基本的显式伴随对象的模板有两个要求:

When defining an explicit companion object for a case class (as of Scala 2.11), to fully replace the compiler provided functionality in the lost implicit companion object, the basic template for the explicit companion object has two requirements:

要求:
1. 必须扩展一个函数定义,该函数定义由一个返回 case 类类型的元组(完全匹配 case 类构造函数参数的类型和顺序)组成
2. 必须重写 toString 函数以提供对象类名称(与关联案例类的名称相同)

Requirements:
1. Must extend a function definition which consists of a tuple (exactly matching the type and order of the case class constructor parameters) returning the type of the case class
2. Must override the toString function to provide the object class name (identical to that of the associated case class)

这是空"显式伴随对象的原始示例代码:

Here's the original example code for the "empty" explicit companion object:

object StreetSecondary {
  //empty for now
}

这是实现上述要求后的示例代码:

And here is the example code after implementing the above requirements:

object StreetSecondary extends ((String, Option[String]) => StreetSecondary) {
    //replace the toString implementation coming from the inherited class (FunctionN)
    override def toString =
      getClass.getName.split("""\$""").reverse.dropWhile(x => {val char = x.take(1).head; !((char == '_') || char.isLetter)}).head
}

为了满足上面的要求 1,extends ((String, Option[String]) => StreetSecondary) 被插入在对象名称之后和第一个花括号之前.

To meet requirement 1 above, extends ((String, Option[String]) => StreetSecondary) is inserted right after the object name and before the first curly brace.

为了满足上面的要求 2,覆盖 def toString = getClass.getName.split("""\$""").reverse.dropWhile(x => {val char = x.take(1).head; !((char == '_') || char.isLetter)}).head 插入到对象的主体中(显式实现仍然有问题)

To meet requirement 2 above, override def toString = getClass.getName.split("""\$""").reverse.dropWhile(x => {val char = x.take(1).head; !((char == '_') || char.isLetter)}).head is inserted in the body of the object (the explicit implementation remains questionable)

深深感谢@drstevens 发布了 javap 输出以帮助我获得信心,以上两个步骤是恢复丢失功能所需的全部.

Deep appreciation to @drstevens for his posting the javap output to help me gain confidence the above two steps are all that are required to restore the lost functionality.

这篇关于如何为 case 类创建一个显式伴随对象,它的行为与替换的编译器提供的隐式伴随对象相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆