how to reflect scala trait class field, use getDeclaredFields but got nothing? - scala

var cl: URLClassLoader = _
var out: TaskStreams = _
var clazz = cl.loadClass("io.marsdigtal.XXX.UserTrait")
if (clazz.isInterface) {
clazz = cl.loadClass(className + "$class")
clazz.getDeclaredFields.foreach { each =>
out.log.info("fieldName: " + each.getName)
}
}
so I use getDeclaredFields, but got nothing...
how can I reflect trait fiedld by scala or java reflection?

This doesn't solve your problem specifically but if someone wants to get a list of fields on a known trait:
new SomeTrait{...}.getClass.getDeclaredFields
I was using this to list fields in a trait hierarchy in dependency / declared order.
[EDIT] There is a caveat. The fields can't be used for 'get'. Obtain the real field on the class instance in question before calling 'get':
val real = cls.getDeclaredField(f.getName)
real.setAccessible(true)
real.get(someInst)

Related

Checking if a Scala List is of class List [duplicate]

I'm trying to incorporate ScalaTest into my Java project; replacing all JUnit tests with ScalaTests. At one point, I want to check if Guice's Injector injects the correct type. In Java, I have a test like this:
public class InjectorBehaviour {
#Test
public void shouldInjectCorrectTypes() {
Injector injector = Guice.createInjector(new ModuleImpl());
House house = injector.getInstance(House.class);
assertTrue(house.door() instanceof WoodenDoor);
assertTrue(house.window() instanceof BambooWindow);
assertTrue(house.roof() instanceof SlateRoof);
}
}
But I have a problem doing the same with ScalaTest:
class InjectorSpec extends Spec {
describe("An injector") {
it("should inject the correct types") {
val injector = Guice.createInjector(new ModuleImpl)
val house = injector.getInstance(classOf[House])
assert(house.door instanceof WoodenDoor)
assert(house.window instanceof BambooWindow)
assert(house.roof instanceof SlateRoof)
}
}
}
It complains that the value instanceof is not a member of Door/Window/Roof. Can't I use instanceof that way in Scala?
Scala is not Java. Scala just does not have the operator instanceof instead it has a parametric method called isInstanceOf[Type].
You might also enjoy watching a ScalaTest Crash Course.
With Scalatest 2.2.x (maybe even earlier) you can use:
anInstance mustBe a[SomeClass]
If you want to be less JUnit-esque and if you want to use ScalaTest's matchers, you can write your own property matcher that matches for type (bar type erasure).
I found this thread to be quite useful: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea
You can then write assertions like:
house.door should be (anInstanceOf[WoodenDoor])
instead of
assert(house.door instanceof WoodenDoor)
The current answers about isInstanceOf[Type] and junit advice are good but I want to add one thing (for people who got to this page in a non-junit-related capacity). In many cases scala pattern matching will suit your needs. I would recommend it in those cases because it gives you the typecasting for free and leaves less room for error.
Example:
OuterType foo = blah
foo match {
case subFoo : SubType => {
subFoo.thingSubTypeDoes // no need to cast, use match variable
}
case subFoo => {
// fallthrough code
}
}
Consolidating Guillaume's ScalaTest discussion reference (and another discussion linked to by James Moore) into two methods, updated for ScalaTest 2.x and Scala 2.10 (to use ClassTag rather than manifest):
import org.scalatest.matchers._
import scala.reflect._
def ofType[T:ClassTag] = BeMatcher { obj: Any =>
val cls = classTag[T].runtimeClass
MatchResult(
obj.getClass == cls,
obj.toString + " was not an instance of " + cls.toString,
obj.toString + " was an instance of " + cls.toString
)
}
def anInstanceOf[T:ClassTag] = BeMatcher { obj: Any =>
val cls = classTag[T].runtimeClass
MatchResult(
cls.isAssignableFrom(obj.getClass),
obj.getClass.toString + " was not assignable from " + cls.toString,
obj.getClass.toString + " was assignable from " + cls.toString
)
}
I use 2.11.8 to do the assertion with collections. The newer syntax is as follows:
val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
scores shouldBe a[Map[_, _]]

"Error occurred in an application involving default arguments" when trying to use Scala's copy method

I'm trying to write a convenience function that replaces the left tree of an immutable binary tree, and I'm getting "Error occurred in an application involving default arguments" in the following replaceL method:
abstract class AbNode {
val key = null
val value = null
val leftTree:AbNode = NullNode
val rightTree:AbNode = NullNode
}
case class Node[K <:Ordered[K],V](k:K, v:V, lT:AbNode, rT:AbNode) extends AbNode {
val key:K = k
val value:V = v
val leftTree:AbNode = lT
val rightTree:AbNode = rT
}
object Node {
def replaceL[K <: Ordered[K],V](newTree:AbNode, node:Node[K,V]): Node[K,V] =
node.copy(leftTree = newTree) //<< Error occurs here
}
case object NullNode extends AbNode {
val key = null
val value = null
val leftTree = NullNode
val rightTree = NullNode
}
The copy method (and default parameters in general) use the name used in the constructor, not the field name that you assign it to (I don't know why this didn't click sooner).
In the case of a case class, the assigned fields are useless; as far as I can tell, they're simply holding a copy of a reference to the constructor value (not my original intent). I think my confusion stemmed from the fact that in C-style languages, the variables given to a constructor are later assigned to a field. In other words, the way I have my classes set-up is non-sensical, they shouldn't have any fields.
My Node class should be simply:
case class Node[K <:Ordered[K],V](k:K, v:V, leftTree:AbNode, rightTree:AbNode) extends AbNode
Which allows copy to see the value I'm referring to.

Mixing dynamic objects with structural typing in Scala

Is it possible to do this? (I'm using scala 2.10) To call a method that requires that the object has a function named "fullName", but the object being built with the Dynamic trait. The compiler complains, but maybe I'm doing it wrong.
I don't need this for any job, I'm just learning the language.
import scala.language.dynamics
object Main extends App {
class MyStatic {
private var privateName = ""
var lastName = ""
def name_= (n: String) {
privateName = n
}
def name = s"***$privateName***"
def fullName = s"$name $lastName"
}
class MyDynamic extends scala.Dynamic {
val map = collection.mutable.Map[String, String]()
def selectDynamic(key: String): String = map(key)
def updateDynamic(key: String)(value: String) {
map += key -> value
}
def applyDynamic(key: String)(value: Any*) = key match {
case "fullName" => {
val name = map("name")
val lastName = map("lastName")
s"$name $lastName"
}
}
}
def showFullName(o: { def fullName: String }) = s"My full name is $o.fullName"
println("Starting App...")
val s = new MyStatic
s.name = "Peter"
s.lastName = "Parker"
println(showFullName(s))
val d = new MyDynamic
d.name = "Bruce"
d.lastName = "Wayne"
println(showFullName(d))
}
The structural type { def fullName: String } basically means "any type with a no-arg method named fullName returning a String.
MyDynamic has no such method, and thus does not comply with this structural type. The fact that MyDynamic extends scala.Dynamic is irreleveant: it means that for any instance of it, you can perform what looks like a call to fullName, but it does not mean that MyDynamic (as a type) has any such member.
So the short answer is no, you cannot mix dynamic objects with structural typing like that.
For completeness, I must add that it could be made to work as you expected, but it would require a special provision from the compiler (namely, the compiler could consider than any type extending scala.Dynamic -- and implementing the required lookup methods -- is compatible with any structural typing, and implement the call not via reflection as is normally done, but by calling the corresponding lookup method).
You are trying to glue together two completely different things. While structural typing is also sometimes compared to 'duck-typing', its feature is exactly the use of static type information (even if on the use site the byte code will call reflection). Per definition, your dynamic type does not have such static type information. So you will never be able to convince the Scala compiler that your dynamic type has a method that can be statically verified to exist.
The only workaround would be to allow any type in showFullName and use reflection to call fullName (again, I'm not sure if this plays out with a dynamic object).
On the other hand, Scala will let you do anything with dynamic types, handing the responsibility over to you:
def showFullName(o: Dynamic) = s"My full name is $o.fullName"
println(showFullName(d))

How do I create a class hierarchy of typed factory method constructors and access them from Scala using abstract types?

(Essentially I need some kind of a synthesis of these two questions (1, 2), but I'm not smart enough to combine them myself.)
I have a set of JAXB representations in Scala like this:
abstract class Representation {
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass())
val writer = new StringWriter
context.createMarshaller.marshal(this, writer)
writer.toString()
}
}
class Order extends Representation {
#BeanProperty
var name: String = _
...
}
class Invoice extends Representation { ... }
The problem I have is with my unmarshalling "constructor" methods:
def unmarshalFromJson(marshalledData: String): {{My Representation Subclass}} = {
val mapper = new ObjectMapper()
mapper.getDeserializationConfig().withAnnotationIntrospector(new JaxbAnnotationIntrospector())
mapper.readValue(marshalledData, this.getClass())
}
def unmarshalFromXml(marshalledData: String): {{My Representation Subclass}} = {
val context = JAXBContext.newInstance(this.getClass())
val representation = context.createUnmarshaller().unmarshal(
new StringReader(marshalledData)
).asInstanceOf[{{Type of My Representation Subclass}}]
representation // Return the representation
}
Specifically, I can't figure out how to attach these unmarshalling methods in a typesafe and DRY way to each of my classes, and then to call them from Scala (and hopefully sometimes by using only abstract type information). In other words, I would like to do this:
val newOrder = Order.unmarshalFromJson(someJson)
And more ambitiously:
class Resource[R <: Representation] {
getRepresentation(marshalledData: String): R =
{{R's Singleton}}.unmarshalFromXml(marshalledData)
}
In terms of my particular stumbling blocks:
I can't figure out whether I should define my unmarshalFrom*() constructors once in the Representation class, or in a singleton Representation object - if the latter, I don't see how I can automatically inherit that down through the class hierarchy of Order, Invoice etc.
I can't get this.type (as per this answer) to work as a way of self-typing unmarshalFromJson() - I get a compile error type mismatch; found: ?0 where type ?0 required: Representation.this.type on the readValue() call
I can't figure out how to use the implicit Default[A] pattern (as per this answer) to work down my Representation class hierarchy to call the singleton unmarshalling constructors using type information only
I know this is a bit of a mammoth question touching on various different (but related) issues - any help gratefully received!
Alex
The key is to not try and attach the method to the class but rather pass it in as a parameter. To indicate the type you are expecting and let the type system handle passing it in. I tried to make the unmarshal invocation something that reads a little DSL like.
val order = UnMarshalXml( xml ).toRepresentation[Order]
The following is a fully testable code snippet
abstract class Representation {
def marshalToXml(): String = {
val context = JAXBContext.newInstance(this.getClass)
val writer = new StringWriter
context.createMarshaller.marshal(this, writer)
writer.toString
}
}
#XmlRootElement
class Order extends Representation {
#BeanProperty
var name: String = _
}
case class UnMarshalXml( xml: String ) {
def toRepresentation[T <: Representation](implicit m:Manifest[T]): T = {
JAXBContext.newInstance(m.erasure).createUnmarshaller().unmarshal(
new StringReader(xml)
).asInstanceOf[T]
}
}
object test {
def main( args: Array[String] ) {
val order = new Order
order.name = "my order"
val xml = order.marshalToXml()
println("marshalled: " + xml )
val received = UnMarshalXml( xml ).toRepresentation[Order]
println("received order named: " + received.getName )
}
}
You should see the following output if you run test.main
marshalled: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><order><name>my order</name></order>
received name: my order
Here's the updated version of Neil's code which I used to support the second use case as well as the first:
case class UnmarshalXml(xml: String) {
def toRepresentation[T <: Representation](implicit m: Manifest[T]): T =
toRepresentation[T](m.erasure.asInstanceOf[Class[T]])
def toRepresentation[T <: Representation](typeT: Class[T]): T =
JAXBContext.newInstance(typeT).createUnmarshaller().unmarshal(
new StringReader(xml)
).asInstanceOf[T]
}
This supports simple examples like so:
val order = UnmarshalXml(xml).toRepresentation[Order]
But also for abstract type based usage, you can use like this:
val order = UnmarshalXml(xml).toRepresentation[T](typeOfT)
(Where you have grabbed and stored typeOfT using another implicit Manifest at the point of declaring T.)

Syntactic sugar for compile-time object creation in Scala

Lets say I have
trait fooTrait[T] {
def fooFn(x: T, y: T) : T
}
I want to enable users to quickly declare new instances of fooTrait with their own defined bodies for fooFn. Ideally, I'd want something like
val myFoo : fooTrait[T] = newFoo((x:T, y:T) => x+y)
to work. However, I can't just do
def newFoo[T](f: (x:T, y:T) => T) = new fooTrait[T] { def fooFn(x:T, y:T):T = f(x,y); }
because this uses closures, and so results in different objects when the program is run multiple times. What I really need is to be able to get the classOf of the object returned by newFoo and then have that be constructable on a different machine. What do I do?
If you're interested in the use case, I'm trying to write a Scala wrapper for Hadoop that allows you to execute
IO("Data") --> ((x: Int, y: Int) => (x, x+y)) --> IO("Out")
The thing in the middle needs to be turned into a class that implements a particular interface and can then be instantiated on different machines (executing the same jar file) from just the class name.
Note that Scala does the right thing with the syntactic sugar that converts (x:Int) => x+5 to an instance of Function1. My question is whether I can replicate this without hacking the Scala internals. If this was lisp (as I'm used to), this would be a trivial compile-time macro ... :sniff:
Here's a version that matches the syntax of what you list in the question and serializes/executes the anon-function. Note that this serializes the state of the Function2 object so that the serialized version can be restored on another machine. Just the classname is insufficient, as illustrated below the solution.
You should make your own encode/decode function, if even to just include your own Base64 implementation (not to rely on Sun's Hotspot).
object SHadoopImports {
import java.io._
implicit def functionToFooString[T](f:(T,T)=>T) = {
val baos = new ByteArrayOutputStream()
val oo = new ObjectOutputStream(baos)
oo.writeObject(f)
new sun.misc.BASE64Encoder().encode(baos.toByteArray())
}
implicit def stringToFun(s: String) = {
val decoder = new sun.misc.BASE64Decoder();
val bais = new ByteArrayInputStream(decoder.decodeBuffer(s))
val oi = new ObjectInputStream(bais)
val f = oi.readObject()
new {
def fun[T](x:T, y:T): T = f.asInstanceOf[Function2[T,T,T]](x,y)
}
}
}
// I don't really know what this is supposed to do
// just supporting the given syntax
case class IO(src: String) {
import SHadoopImports._
def -->(s: String) = new {
def -->(to: IO) = {
val IO(snk) = to
println("From: " + src)
println("Applying (4,5): " + s.fun(4,5))
println("To: " + snk)
}
}
}
object App extends Application {
import SHadoopImports._
IO("MySource") --> ((x:Int,y:Int)=>x+y) --> IO("MySink")
println
IO("Here") --> ((x:Int,y:Int)=>x*y+y) --> IO("There")
}
/*
From: MySource
Applying (4,5): 9
To: MySink
From: Here
Applying (4,5): 25
To: There
*/
To convince yourself that the classname is insufficient to use the function on another machine, consider the code below which creates 100 different functions. Count the classes on the filesystem and compare.
object App extends Application {
import SHadoopImports._
for (i <- 1 to 100) {
IO(i + ": source") --> ((x:Int,y:Int)=>(x*i)+y) --> IO("sink")
}
}
Quick suggestion: why don't you try to create an implicit def transforming FunctionN object to the trait expected by the --> method.
I do hope you won't have to use any macro for this!