Reputation: 941
I am trying to use private trait field in testing. Very simple example:
//Works fine with class A, but not trait A
trait A {
private val foo = "Some string"
}
class Test extends A {
val field = classOf[A].getDeclaredField("foo")
field.setAccessible(true)
val str = field.get(this).asInstanceOf[String]
}
I got:
java.lang.NoSuchFieldException: foo at java.lang.Class.getDeclaredField
live example here
How to get this snippet executable?
Upvotes: 3
Views: 3770
Reputation: 16224
Edit special thanks to @Seth Tisue (up votes and accept to him please)
class Test extends A {
val field:Field = this.getClass.getDeclaredField("A$$foo")
field.setAccessible(true)
println(field.get(this).asInstanceOf[String])
}
"A$$foo" is the correct way to get the super type attribute, this and use this.getClass
.
I didn't know it before, but with that correction, your code will work just great!
First Idea:
trait A {
private val foo = "Some string"
}
class Test extends A {
val fields: Seq[Field] = this.getClass.getDeclaredFields.toList
val field = fields.filter(x => {
println(x.getName)
x.getName.contains("foo")
}).head
field.setAccessible(true)
println(field.get(this).asInstanceOf[String])
}
As you can see, when you print the name of the "foo" variable, is not really "foo", it's something else:
A$A295$A$A295$A$$foo
in my case, and that's why you (and I) got the error
java.lang.NoSuchFieldException: foo at java.lang.Class.getDeclaredField
So, my idea for now, I hope someone came with a better one, is look if "foo" is inside the variable name "A$A295$A$A295$A$$foo" so you can tell thats the variable you where looking for.
Upvotes: 4
Reputation: 30453
A
is a trait, which Scala translates to a JVM interface. Interfaces can't have fields, so there is no such field. The underlying field only gets added once the interface is actually mixed into a class.
So the first thing you would need to do get this is running is change classOf[A]
to classOf[Test]
.
The second thing is to change getDeclaredField("foo")
to .getDeclaredField("A$$foo")
.
Upvotes: 6