1
abstract class A {
  protected[this] type ThisType = this.type
  protected[this] type OtherType = this.type 

  def assign(other: OtherType): ThisType
}

class B extends A {
  def assign(other: OtherType): ThisType = ???
}

class C extends A {
  def assign(other: OtherType): ThisType = ???
}

class D extends C {
  def assign(other: OtherType): ThisType = ???
}

How do I make sure the other type received in assign of and object of type B is also B. e.g. how can I write something effectively like:

def f1(p1: A, p2: A) = p1.assign(p2)
def f2[T <: A](p1: T, p2: T) = p1.assign(p2)

I am getting following errors:

Error at p1 Error at p2

NB: Actually ThisType and OtherType should be the same but I seperated them so I can try out different options.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321

1 Answers1

1

One way of achieving what you want can be done using Type Projections:

def main(args: Array[String]): T = {
  f1(new C, new C)
}

abstract class A {
  type ThisType <: A
  def assign(other: ThisType): ThisType
}

class C extends A {
  override type ThisType = C
  override def assign(other: C): C = ???
}

class D extends C {
  override type ThisType = D
  override def assign(other: D): D = ???
}

def f1[T <: A](p1: T#ThisType, p2: T#ThisType) = p1.assign(p2)

Another way can be using F-bound polymorphism:

abstract class A[T <: A[T]] {
  def assign(other: T): T
}

class C extends A[C] {
  override def assign(other: C): T = ???
}

def f1[T <: A[T]](p1: T, p2: T) = p1.assign(p2)
Community
  • 1
  • 1
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • I was trying to avoid F-bound polymorphism hence Type Projections approach was what I was after. That's why I defined the class like above but providing both makes the answer compete. Thanks for this. – Suminda Sirinath S. Dharmasena Oct 01 '16 at 17:41
  • I have a follow up question: http://stackoverflow.com/questions/39809778/how-do-you-use-type-projections-to-p1-and-p2-are-the-same-type-in-p1-assignp2. I actually cannot use signature of `def f1[T <: A](p1: T#ThisType, p2: T#ThisType) = p1.assign(p2)` for my problem (though this is not what I endted asking in this question). I can only have `def run: Unit` – Suminda Sirinath S. Dharmasena Oct 01 '16 at 17:58