Reputation: 959
Hi so I have this use case where I have a function which takes a type which extends a trait. Let's say the trait a is:
trait A {
val a: Double
}
Now I have multiple case classes that extend a.
case class B(val a: Double) extends A
case class C(val a: Double, val b: Double) extends A
Now I want a generalized funtion such as:
def change[T <: A](newA: Double, state: T): T = {
state.copy(a = newA)
}
If I can some how specify that the generic T is a case class that extends A, I can than infer that state has a clone method that has a param a. Or maybe there is a way to define a generic that says that there is a clone function that has exactly one param that is a.
Thanks
Upvotes: 2
Views: 376
Reputation: 34463
Building on a comment by cchantep, and on a similar question I have asked recently, following works:
trait A[T <: A[T]] {
val a: Double
def clone(a: Double = a): T
}
case class B(a: Double) extends A[B] {
def clone(a: Double = a) = copy(a = a)
}
case class C(a: Double, b: Double) extends A[C] {
def clone(a: Double = a) = copy(a = a)
}
def change[T <: A[T]](newA: Double, state: T): T = {
state.clone(a = newA)
}
Is there any reason why do you want change
to return the specific type and not just A
? Without this requirement is could be a lot simpler, I have added the recursive type only to meet this requirement (to describe clone
is always returning the original type):
trait A {
val a: Double
def clone(a: Double = a): A
}
case class B(a: Double) extends A {
def clone(a: Double = a) = copy(a = a)
}
case class C(a: Double, b: Double) extends A {
def clone(a: Double = a) = copy(a = a)
}
def change(newA: Double, state: A): A = {
state.clone(a = newA)
}
Even with this simple implementation you could use clone
directly instead of change
and it would still keep the derived type statically. Still, I think such requirement makes little sense, and in the situations you compiler knows it is B
or C
, not A
, you can use copy directly, you need change
only when you have A
only.
Upvotes: 1