lundi 30 juillet 2018

Scala design pattern - sealed trait with two generics, children method having same type object in arguments list

sorry if the title is not very explicative, but I don't know how to explain it. I'm a scala newbie and I'm struggling in finding a solution to my problem. Here's the snippet:

sealed trait Base[T, M] {
  var value: Option[T] = None

  def initialize(v: T): this.type = {
    value = Some(v)
    this
  }
  def combine[K <: M](other: K): M

}

class Child1 extends Base[String, Child1] {

  override def combine[K <: Child1](other: K) = {
    val c = new Child1()
    c.initialize(value.get + " - " + other.value.get)
    c
  }

}

class Child2 extends Base[Long, Child2] {
  override def combine[K <: Child2](other: K) = {
    val c = new Child2()
    c.initialize(value.get + other.value.get)
    c
  }
}


object Main extends App {
  val c1a = new Child1()
  c1a.initialize("a")
  val c1b = new Child1()
  c1b.initialize("b")

  val c21 = new Child2()
  c21.initialize(1)
  val c22 = new Child2()
  c22.initialize(2)

  val m1 = Map("child1" -> c1a, "child2" -> c21)
  val m2 = Map("child1" -> c1b, "child2" -> c22)

  m1("child1").combine(m2("child1"))
}

What I want to achieve is that each subclass of Base can be combined only with objects of the same type.

The compiler complains when calling the combine method due to a mismatch in the type of the argument. Is this a correct approach? Or the structure of the classes for my purpose is to be rewritten?

EDIT:

This should be ok as well:

sealed trait Base[T, M] {
  var value: Option[T] = None

  def initialize(v: T): this.type = {
    value = Some(v)
    this
  }
  def combine(other: M): M

}

class Child1 extends Base[String, Child1] {

  override def combine(other: Child1) = {
    val c = new Child1()
    c.initialize(value.get + " - " + other.value.get)
    c
  }

}

class Child2 extends Base[Long, Child2] {
  override def combine(other: Child2) = {
    val c = new Child2()
    c.initialize(value.get + other.value.get)
    c
  }
}

Aucun commentaire:

Enregistrer un commentaire