I've always understood the constructor arguments of case classes as defining public vals.
However, when I reflect the fields, the isPublic method comes up false. Any ideas why?
scala> class Test( val name : String, val num : Int )
defined class Test
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> val tpe = typeOf[Test]
tpe: reflect.runtime.universe.Type = Test
scala> def checkValVisibility( t : Type ) = {
| t.members
| .filter( _.isTerm )
| .map( _.asTerm )
| .filter( _.isVal )
| .map( memb => "Val " + memb.name.toString.trim + " is public? " + memb.isPublic )
| .mkString("\n")
| }
checkValVisibility: (t: reflect.runtime.universe.Type)String
scala> checkValVisibility( tpe )
res2: String =
Val num is public? false
Val name is public? false
The reason is that the actual values that you queried for num
and name
are indeed private. For case classes (and classes with public class parameters), class parameters are implemented as private fields with public accessors (which are generated automatically for you).
If you want to use Scala Reflection to obtain a symbol representing the public accessor for a given field, you can simply do:
scala> tpe.member("name": TermName)
res02: reflect.runtime.universe.Symbol = value name
You can see that it's a public accessor if you do:
scala> tpe.member("name": TermName).isPublic
res03: Boolean = true
scala> tpe.member("name": TermName).isMethod
res04: Boolean = true
In your case, you filtered out the accessors, leaving only the actual (private) fields. You can change your code from above to achieve what you want by instead checking with isAccessor
(or isGetter
) instead of isVal
.
scala> def checkValVisibility( t : Type ) = {
| t.members
| .filter( _.isTerm )
| .map( _.asTerm )
| .filter( _.isAccessor )
| .map( memb => "Val " + memb.name.toString.trim + " is public? " + memb.isPublic )
| .mkString("\n")
| }
checkValVisibility: (t: reflect.runtime.universe.Type)String
scala> checkValVisibility(tpe)
res05: String =
Val num is public? true
Val name is public? true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With