具有通用类型的Scala复制案例类 [英] Scala copy case class with generic type

查看:52
本文介绍了具有通用类型的Scala复制案例类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类 PixelObject ImageRefObject 和其他一些类,但这只是这两个类,以简化操作.它们都是包含一个uid的 trait Object 的子类.我需要通用方法,该方法将使用给定的新 uid 复制案例类实例.我之所以需要它,是因为我的任务是创建一个类ObjectRepository,该类将保存 Object 的任何子类的实例,并使用新的 uid 返回它.我的尝试:

I have two classes PixelObject, ImageRefObject and some more, but here are just these two classes to simplify things. They all are subclasses of a trait Object that contains an uid. I need universal method which will copy a case class instance with a given new uid. The reason I need it because my task is to create a class ObjectRepository which will save instance of any subclass of Object and return it with new uid. My attempt:

trait Object {
  val uid: Option[String]
}

trait UidBuilder[A <: Object] {
  def withUid(uid: String): A = {
    this match {
      case x: PixelObject => x.copy(uid = Some(uid))
      case x: ImageRefObject => x.copy(uid = Some(uid))
    }
  }
}

case class PixelObject(uid: Option[String], targetUrl: String) extends Object with UidBuilder[PixelObject]

case class ImageRefObject(uid: Option[String], targetUrl: String, imageUrl: String) extends Object with UidBuilder[ImageRefObject]

val pix = PixelObject(Some("oldUid"), "http://example.com")

val newPix = pix.withUid("newUid")

println(newPix.toString)

但是出现以下错误:

➜  ~  scala /tmp/1.scala
/tmp/1.scala:9: error: type mismatch;
 found   : this.PixelObject
 required: A
      case x: PixelObject => x.copy(uid = Some(uid))
                                   ^
/tmp/1.scala:10: error: type mismatch;
 found   : this.ImageRefObject
 required: A
      case x: ImageRefObject => x.copy(uid = Some(uid))
                                      ^
two errors found

推荐答案

我会坚持使用Seam提出的解决方案.我在几个月前做了同样的事情.例如:

I would stick with the solution proposed by Seam. I have done the same a couple of months ago. For example:

trait Entity[E <: Entity[E]] {
  // self-typing to E to force withId to return this type
  self: E => def id: Option[Long]
  def withId(id: Long): E
}
case class Foo extends Entity[Foo] {
  def withId(id:Long) = this.copy(id = Some(id))
}

因此,您不必在实现本身的所有定义中定义方法,而不是为特征的所有实现定义具有匹配项的UuiBuilder.您可能不想每次添加新的实现时都修改UuiBuilder.

So, instead of defining an UuiBuilder with a match for all implementations of your trait, you define the method in your implementation itself. You probably don't want to modify UuiBuilder every time you add a new implementation.

此外,我还建议您使用自定义类型来强制withId()方法的返回类型.

In addition, I would also recommend you to use a self typing to enforce the return type of your withId() method.

这篇关于具有通用类型的Scala复制案例类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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