简体   繁体   中英

Defining a scala trait def that returns a concrete sub type instance

I am attempting to define a base trait used for a simple CRUD system. However, I need the base trait to support a "copyWithId" def (since the Scala case class magic for copy is not available). The best approach I have found so far is:

trait Identifiable[ID, T] {
  def id: Option[ID]
  def copyWithId(id: Option[ID]): T
}

case class TestNamedIdentity(id: Option[Int], name: String) 
    extends Identifiable[Int, TestNamedIdentity] {

  def copyWithId(id: Option[Int]): TestNamedIdentity = {
    copy(id = id)
  }
}

This works but looks a bit clunky because it requires all the concrete instances to extend with ID and Self. I'd like to write something like the following:

trait Identifiable[ID] {
  this:X =>
  def copyWithId(id: Option[ID]): X
  def id: Option[ID]
}

Using some form of self-reference to the concrete class. Any way to make this work?

Update: With use case below

The idea is to use it in code like

abstract class SomeClass[A <: IdentifiableEntity[ID], ID] {
  def someFunc2: Option[ID]
  def someFunc(item: A): A = {
    item.copyWithId(someFunc2)
  }
}

Using the solution from @jwvh requires "asInstanceOf" casting after the call. Which for my use case works, but was hoping for a more elegant solution.

    item.copyWithId(someFunc2).asInstanceOf[A]

This appears to work.

trait Identifiable[ID] {
  def id: Option[ID]
  def copyWithId(id: Option[ID]): Identifiable[ID]
}

Then the case class is simplified.

case class TestNamedIdentity(id: Option[Int], name: String
                            ) extends Identifiable[Int] {
  def copyWithId(id: Option[Int]): TestNamedIdentity = copy(id = id)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM