Scala: Two methods, different parameter types but

2020-06-23 08:23发布

问题:

I have the following classes:

case class Vec2(x: Int, y: Int) { def +(other: Vec2) = Vec2(x + other.x, y + other.y) }
case class Vec3(x: Int, y: Int, z: Int) { def +(other: Vec3) = Vec3(x + other.x, y + other.y, z + other.z) }

And the following methods:

def doStuff1(a: Vec2, b: Vec2) = (a, a + b)
def doStuff2(b: Vec3, b: Vec3) = (a, a + b)

My question: How can I merge these two functions into one generic one in a type-safe manner? The classes may be altered in any way.

Something like

def doStuff[V](a: V, b: V) = (a, a + b)

obviously won't work, because of the call to the "+" method. I've tried all kinds of crazy stuff (common base class with abstract type, explicitly typed self references, variances, ...) but couldn't come up with a solution.

The best idea I could come up with is a runtime-check (pattern matching or isInstanceOf/asInstanceOf), but that doesn't satisfy the type safety requirement. I just think/hope there must be a better way to do this.

回答1:

trait Vector[V <: Vector[V]] { this: V =>
  def +(other: V): V
}

case class Vec2(x: Int, y: Int) extends Vector[Vec2] {
  override def +(other: Vec2): Vec2 = Vec2(x + other.x, y + other.y)
}

case class Vec3(x: Int, y: Int, z: Int) extends Vector[Vec3] {
  override def +(other: Vec3): Vec3 = Vec3(x + other.x, y + other.y, z + other.z)
}

def doStuff[V <: Vector[V]](a: V, b: V): (V, V) = (a, a + b)


回答2:

You could try some kind of Structural Type. Like this:

def doStuff[V <: {def +(other: V): V }](a: V, b: V) = (a, a + b)


标签: scala