You should make it so that the "move" happens on the type T itself and return type T. But then the compiler will complain about not being sure that you are returning a T because the actual type of T will be determined for the use of move and compiler has no evidence to determine that it was a Circle as match-case is a runtime thing.
Which means you need to provide evidence which can be used at compile-time to move any instance of type T.
import scala.language.implicitConversions trait Figure { def x:Int def y:Int } case class Circle(x:Int, y: Int, radio: Double) extends Figure case class Rectangle(x:Int, y: Int, width: Int, high: Int) extends Figure
Now, let us build the required evidence which will be used to "enrich" our Figure instances
trait MoveSupport[F <: Figure] { val f: F def move(x: Int, y: Int): F } object MoveSupport { class CircleMoveSupport(val f: Circle) extends MoveSupport[Circle] { override def move(x: Int, y: Int): Circle = f.copy(x = f.x + x, y = f.y + y) } class RectangleMoveSupport(val f: Rectangle) extends MoveSupport[Rectangle] { override def move(x: Int, y: Int): Rectangle = f.copy(x = f.x + x, y = f.y + y) } implicit def toCircleMoveSupport(circle: Circle) = new CircleMoveSupport(circle) implicit def toRectangleMoveSupport(rectangle: Rectangle) = new RectangleMoveSupport(rectangle) }
Now, we can use these evidence to "enrich" our Figure types to have move support.
import MoveSupport._ val circle = Circle(1, 1, 1) // circle: Circle = Circle(1,1,1.0) val circle2 = circle.move(1, 1) // circle2: Circle = Circle(2,2,1.0)
Or, you can build your Motor using these evidence.
object Motor { import MoveSupport._ def move[T <: Figure](x: Int, y: Int, figure: T)(implicit ev: T => MoveSupport[T]): T = figure.move(x, y) } val c = Circle(1, 1, 1) // circle: Circle = Circle(1,1,1.0) val c1 = Motor.move(1, 1, c) // circle1: Circle = Circle(2,2,1.0)
movebeing aFigureand not a concrete class like Circle or Rectangle. To get to the underlying concrete class you can use pattern matching as you have done in the method above.