问题是我有一些具有不同字段的独立案例类。 我想编写一个方法,返回给定类型的case类的实例,其中一个参数已更改。
def updateParam[C : ClassTag](c: C, paramName: String, paramValue: Any): C = ...
我利用this answer,但它涉及使用不那么美丽的反射机制。 是否有可能避免使用反射,或者至少隐藏在某些库的引擎盖下?
答案 0 :(得分:1)
如果要在不同类的实例上调用相同的函数,则它是多态。
如果这些类不相关,则多态性为 ad-hoc 。
在Scala中实现ad-hoc多态的常用方法是使用类型类。在这里,您可以实现类型类Copyable
:
trait Copyable[C] {
def copy(c: C, paramName: String, value: Any): C
}
并按如下方式实施您的方法:
def updateParam[C: Copyable](c: C, paramName: String, paramValue: Any): C = {
implicitly[Copyable[C]].copy(c, paramName, paramValue)
}
现在,如果您有两个不相关的类,尽管您希望在相同的上下文中使用它们,但它们在某种程度上最终无关:
case class Foo(paramName: String, foo: Int)
case class Bar(paramName: String, bar: Option[Double])
您可以提供使其成为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 + "`")
}
}
}
然后像这样使用你的方法:
val f = Foo("hello", 42)
val b = Bar("bye", Some(58.0))
println(updateParam(f, "paramName", "hello, world"))
println(updateParam(b, "paramName", "obey"))
然后打印:
Foo(hello, world,42)
Bar(obey,Some(58.0))
但是,当你可以这样做的时候,你想要的并不完全清楚。 Foo
和Bar
在同样的情况下最终是如何发生的,所以最终基本上是鸭子打字,需要方法copy
?也许你应该首先消除根本原因。
您可能还想看一下镜头。