In Scala it's possible to use the annotation #BeanProperty to automatically generate getters and setters to a field.
How can I create my own annotation that behaves like that?
I'm interested in creating annotations that changes the source code, like #BeanProperty does.
As an example, how could I create an annotation that only generated get methods?
Thanks.
Two words: compiler plugin. It is not easy, and the documentation is sparse, but that is one way to do it.
Future versions of Scala will likely have macro support, which gives you much of the same flexability.
Related
Not sure if it's possible, but given a case class in Scala, I would like to generate another class and some methods using reflection.
For example, Phantom table definition, which must have a specific object extends to a column type. Those things will have much less error-prone if I can generate them instead of hand code them.
IntelliJ live template doesn't seem can allow me to do this.
I was quickly reading Scala Marco
http://docs.scala-lang.org/overviews/macros/overview
and this:
http://docs.scala-lang.org/overviews/macros/implicits.html
But I still have no idea how to apply it to IDE yet.
still reading, if anyone has done something like T4 in Scala programming, please share some insight. Thanks
is there a way to define custom annotations in Scala without resorting the use Java interfaces?
I saw this answer which says it's not possible, but is pretty old (dates back to 2010).
But, even with a recent Scala 2.11.8 compiler, I got the usual message:
warning: Implementation restriction: subclassing Classfile does make your annotation visible at runtime. If that is what you want, you must write the annotation class in Java.
I'm kinda puzzled: it's 2016 and yet, seems like we can't create annotations natively from Scala. Is there any reason about this, or am I doing it wrong somehow?
Thanks!
I would like to create an annotation or trait that adds methods to an object at compile time dynamically, based on existing fields. Although I'm interested in something at the class-level, I'd also work with field-level annotations (or something else more granular) as well.
An older stack-overflow question asking about the implementation details of Scala's #BeanProperty was answered with, "It's a compiler plugin, but macros may also allow you to do this". Given the official (if experimental) release of macros in Scala 2.10, is this sort of functionality now possible?
Update: This answer is not valid anymore. See Eugenes comment.
No, it is not yet possible.
In 2.10 there exists only def macros that can't do anything comparable. For 2.11 the world is a bit better, macro annotations and an implementation to introduce members to classes already exists. But they are only some weeks old and therefore will work only for some corner cases. Furthermore the implementation to introduce members to classes lives in a different branch than the implementation for macro annotations, thus it is not yet possible to use them together.
I'd really like to use case classes' copy feature in my project, but unfortunately I also need inheritance, which doesn't work well with case classes. So, I'm wondering if it's possible to write a macro which will generate a method for creating copy-with-changes object for an arbitrary class. What stops me there at the moment is the fact that AFAIK macros don't support named parameters. Has anyone found a way around that or, alternatively, can suggest other way for easy creating of copies which use inheritance?
That will be possible with type macros and/or annotation macros. The current macros do not support this.
Do look at lenses work, though. There's quite a few macro-based versions around, such as Shapeless.
You could also take a look at https://github.com/dicarlo2/ScalaEquals
Does Project Lombok offer any benefit compared to code templates / code generation in Eclipse? Are there any downsides (apart from including the .jar)?.
One advantage of Lombok is that once you've annotated a class with, say, the #Data annotation, you never need to regenerate the code when you make changes. For example, if you add a new field, #Data would automatically include that field in the equals, hashCode and toString methods. You'd need to manually make that change when using Eclipse generated methods. Some of the time, you may prefer the manual control but for most cases, I expect not.
The advantage of Lombok is that the code isn't actually there - i.e. classes are much more readable and are not cluttered.
Advantages:
Very easy to use
Classes are much cleaner ('no boilerplate code'),especially
'struct'-like inner classes shrink to a bare minimum:
#Data
private class AttrValue {
private String attribute;
private MyType value;
}
This will create both getters and setters, a toString(), and correct hash() / equals() methods including both variables.
The variant with #Value creates an immutable structure (no setters, all fields final).
No need to generate/remove code when you change fields (getters, setters, toString, hash, equals)
No interference with hand-coded methods: just add you own specific setter to the class where needed. Lombok skips this and generates everything else
Disadvantages:
No name refactoring, yet: renaming value above will not (yet) rename getValue() and setValue()
May slows down ecplise slightly
toString output not as nice as, for instance, ToStringBuilder from apache commons
Very few come to mind:
it is based on annotation, so no good for legacy project still in pre-Java5 (delombok can help). Actually, it requires using the javac v1.6 compiler.
it still have limitations regarding multiple constructors
The dependency issue is not to be overlooked though, but you have excluded it from your question.
Eclipse EMF offers some features which are very handy which Lombock does not yet support:
Powerful notification mechanims to get informed about changes in your instances
Generic API without java reflection. Access and modify instances without a strong reference to the type
Command und API based editing
Cross references between models: Create and load model trees and EMF handles the loading by creating a proxy for the cross reference. This saves memory and boost performance in huge domain trees
And much more...