Reputation: 3130
I have a case class:
case class Cow(breed: Breed, gender: Gender)(implicit grass: Pasture) {
val hasSpots: Boolean
}
How can I use reflection at runtime to get back just the list (breed
, gender
)? Here's what doesn't work:
def getConstructorParams[C](implicit ct: ClassTag[C]) =
ct.runtimeClass.getDeclaredFields.map(_.getName)
// returns (breed, gender, grass, hasSpots)
def getConstructorParams[C](implicit ct: ClassTag[C]) =
ct.runtimeClass.getConstructors.head.getParameters.map(_.getName)
// returns (arg0, arg1, arg2)
The first solution includes non-constructor fields (hasSpots
), which is not what I want. The second solution loses the parameter names. Both methods also include the curried implicit grass/arg2
argument, which I also don't want.
Is there some way to get back just the (breed
, gender
) fields?
Upvotes: 1
Views: 570
Reputation: 7768
Assuming you're using the scala-reflect API (I tested it with 2.12 but it may work with other versions), you could do
import scala.reflect.runtime.universe._
def getConstructorParams[T: TypeTag] =
typeOf[T].decl(termNames.CONSTRUCTOR)
.alternatives.head.asMethod // this is the primary constructor
.paramLists.head.map(_.asTerm.name.toString)
getConstructorParams[Cow] == List("breed", "gender")
Upvotes: 3