scala: annotating accessor methods - scala

class Foo {
#SomeAnnotation
var bar: String = _
}
#SomeAnnotation is a Java annotation (so it is kept at runtime) with runtime retention and Method target. The code compiles, but at runtime the bar() and bar_=() methods that the compiler generated are not annotated.
Assuming this is not a bug, is there a clean way of annotating the generated getter method without needing to def the method explicitly?

This mailing list post might be of use:
http://old.nabble.com/-scala--field-annotations,-getters-setters-and-BeanProperty-td24970781.html

Yes, you need to use the meta-annotations in scala.annotation.target. See the documentation in https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/annotation/target/getter.scala

Related

How can I provide a scala companion object's class to Java?

I have a Java code that looks for annotations in static methods of a class.
processor.readStatics( MyClass.class ); // Takes Class<?>
How can I provide the methods of a scala companion object to this function from within scala?
class MyClass {
}
object MyClass {
def hello() { println("Hello (object)") }
}
I seems that:
MyClass$.MODULE$.getClass()
should be the answer. However, MyClass$ seems to be missing from scala (in 2.10, at least) and only visible to Java.
println( Class.forName("MyClass$.MODULE$") )
also fails.
Class name is MyClass$ (with the appropriate package name prepended).
println(Class.forName("MyClass$")) will print out "class MyClass$".
MyClass$.MODULE$ is the instance of the class, referencing the singleton object.
println(MyClass$.MODULE$ == MyClass) will print out "true" even though, when compiling, you will get a warning that this comparison always yields false :)
Note, that none of this works in repl for some reason. You need to actually create a .scala file, compile it with scalac, and run.
So, in java, use MyClass$ to reference the class of MyClass object statically, use MyClass$.MODULE$ to reference the singleton instance of MyClass object, use MyClass$.class or MyClass$.MODULE$.getClass() to reference the class of the singleton object dynamically, use Class.forName("MyClass$") to access it at runtime by name.
The shortest and type-safest solution is to simply use
MyClass.getClass
I would have hoped the following to work, but apparently scalac is not happy with it:
classOf[MyClass.type]

Use `#annotation.varargs` on constructors

I want to declare a class like this:
class StringSetCreate(val s: String*) {
// ...
}
and call that in Java. The problem is that the constructor is of type
public StringSetCreate(scala.collection.Seq)
So in java, you need to fiddle around with the scala sequences which is ugly.
I know that there is the #annotation.varargs annotation which, if used on a method, generates a second method which takes the java varargs.
This annotation does not work on constructors, at least I don't know where to put it. I found a Scala Issue SI-8383 which reports this problem. As far as I understand there is no solution currently. Is this right? Are there any workarounds? Can I somehow define that second constructor by hand?
The bug is already filed as https://issues.scala-lang.org/browse/SI-8383 .
For a workaround I'd recommend using a factory method (perhaps on the companion object), where #varargs should work:
object StringSetCreate {
#varargs def build(s: String*) = new StringSetCreate(s: _*)
}
Then in Java you call StringSetCreate.build("a", "b") rather than using new.

Can I generate foo_= and foo accessors from setFoo and getFoo?

I'm getting started with using Scala on Android and a lot of the accessor methods are standard JavaBeans accessors, e.g. setTitle(...) and getTitle(). It's a lot nicer to use the title_= and title methods in scala, so I can write code like:
button.title = "Foo"
Is there any way to automatically map these from JavaBeans-style accessors, maybe using the Dynamic trait?
I think Dynamic would work, except it is not presently supported with syntactic sugar. Also, it would return AnyRef since there's no way to pass what the expected return type is.
Of course, you can simply use pimp my library to add appropriate Scala-style getters and setters.
I'm not sure this is supported on Android, but you can use #BeanProperty:
class X {
#scala.reflect.BeanProperty
var y:String = _
}
val x = new X()
x.setY("Test")
println(x.getY) //--> Test
There are more annotations for Bean support, e.g. #BooleanBeanProperty and #BeanInfo.
I don't think the dynamic trait will help you. I guess you need reflection to use the methods and they will not be discoverable through reflection.
I think you're best chance is to create a scala compiler plugin (see http://www.scala-lang.org/node/140 and http://www.sts.tu-harburg.de/people/mi.garcia/ScalaCompilerCorner/).

Dynamic Proxy using Scalas new Dynamic Type

Is it possible to create an AOP like interceptor using Scalas new Dynamic Type feature? For example: Would it be possible to create a generic stopwatch interceptor that could be mixed in with arbitrary types to profile my code? Or would I still have to use AspectJ?
I'm pretty sure Dynamic is only used when the object you're selecting on doesn't already have what you're selecting:
From the nightly scaladoc:
Instances x of this trait allow calls x.meth(args) for arbitrary method names meth and argument lists args. If a call is not natively supported by x, it is rewritten to x.invokeDynamic("meth", args)
Note that since the documentation was written, the method has been renamed applyDynamic.
No.
In order for a dynamic object to be supplied as a parameter, it'll need to have the expected type - which means inheriting from the class you want to proxy, or from the appropriate superclass / interface.
As soon as you do this, it'll have the relevant methods statically provided, so applyDynamic would never be considered.
I think your odds are bad. Scala will call applyDynamic only if there is no static match on the method call:
class Slow {
def doStuff = //slow stuff
}
var slow = new Slow with DynamicTimer
slow.doStuff
In the example above, scalac won't call applyDynamic because it statically resolved your call to doStuff. It will only fall through to applyDynamic if the method you are calling matches none of the names of methods on the type.

Type aliasing Java classes with statics

Suppose MyClass is a class defined in Java, and has many static as well as non-static members. I tried to alias this class (and associated companion object) in a Scala object MyObject as shown below:
object MyObject {
import javastuff._
type MyAlias = MyClass
val MyAlias = MyClass
}
Scalac complains:
error: object MyClass is not a value
val MyAlias = MyClass
How do I work around this? Thanks.
Although this works in pure Scala for a class + companion object, it's not possible with Java's static methods, as these don't belong to any interface.
Scala could, in theory, create an object containing delegates to all the static methods of some class, but it doesn't do this currently. It's also possible to write a compiler plugin for this if you feel comfortable writing plugins.
Failing that, you'll either have to create an object full of delegates yourself, or just cherry-pick a few methods and pass them around as functions.
it's not possible with Java's static methods, as these don't belong to any interface.
Update 5 years later: PR 5131 mentions:
We used to disable generation of static forwarders when a object had a
trait as a companion, as one could not add methods with bodies to an
interface in JVM 6.
The JVM lifted this restriction to support default methods in interfaces,
so we can lift the restriction on static forwarders, too.
Fixes scala-dev issue 59
See commit 41c9a17 by Jason Zaugg (retronym).