If you want to invoke same function on instances of different classes, then it is polymorphism.
If those classes are unrelated, the polymorphism is ad-hoc.
The usual way to implement ad-hoc polymorphism in Scala is by using typeclasses. Here, you can implement the typeclass Copyable
:
trait Copyable[C] {
def copy(c: C, paramName: String, value: Any): C
}
and implement your method as follows:
def updateParam[C: Copyable](c: C, paramName: String, paramValue: Any): C = {
implicitly[Copyable[C]].copy(c, paramName, paramValue)
}
Now, if you have two unrelated classes, which somehow ended up unrelated despite the fact that you want to use them in the same context:
case class Foo(paramName: String, foo: Int)
case class Bar(paramName: String, bar: Option[Double])
you can provide type-classes that make them Copyable
:
implicit object FooIsCopyable extends Copyable[Foo] {
def copy(f: Foo, paramName: String, value: Any): Foo = {
if (paramName == "paramName") {
f.copy(paramName = value.asInstanceOf[String])
} else if (paramName == "foo") {
f.copy(foo = value.asInstanceOf[Int])
} else {
throw new IllegalArgumentException("Foo has no param `" + paramName + "`")
}
}
}
implicit object BarIsCopyable extends Copyable[Bar] {
def copy(b: Bar, paramName: String, value: Any): Bar = {
if (paramName == "paramName") {
b.copy(paramName = value.asInstanceOf[String])
} else if (paramName == "bar") {
b.copy(bar = value.asInstanceOf[Option[Double]])
} else {
throw new IllegalArgumentException("Bar has no param `" + paramName + "`")
}
}
}
and then use your method like this:
val f = Foo("hello", 42)
val b = Bar("bye", Some(58.0))
println(updateParam(f, "paramName", "hello, world"))
println(updateParam(b, "paramName", "obey"))
which then prints:
Foo(hello, world,42)
Bar(obey,Some(58.0))
However, while you can do this, it's not entirely clear why you would want to. How did it happen that Foo
and Bar
end up in the same situation, so that you end up with essentially duck-typing, requiring method copy
? Maybe you should eliminate the root-cause in the first place.
You might also want to take a look at lenses.