I'd like to know if there is any way to add methods to library classes using Groovy traits.
From what I read here #Mixin is used for this, or you can use the runtime mixin approach with metaclass. Since #Mixin is now deprecated in favor of traits, any chance to achieve the same behavior by using traits or is runtime mixin the only option?
Thank you
Groovy also supports implementing traits dynamically at runtime. It
allows you to "decorate" an existing object using a trait.
You can decorate an object, however, I am afraid that it is not possible to decorate a class so that all its instances have the method available. See below a simple example that may help you or find more details here.
trait Extra {
String extra() { "I'm an extra method" }
}
class Something {
String doSomething() { 'Something' }
}
def s = new Something() as Extra
assert s.extra() == "I'm an extra method"
assert s.doSomething() == 'Something'
Related
The example below will type-check and compile correctly in Groovy 2.5.
I would like to define the traits in two separate source files for clarity. This split leads to a undefined static type for the property access B.a in x().
Question: Is there a way to configure or hint the type check so it considers the definition of the trait?
It seems that this property is quite desirable, given that multiple inheritance is tricky and a type-check is especially valuable under these
circumstances.
package traits.example
import groovy.transform.CompileStatic
#CompileStatic
trait A {
String a
}
trait B implements A {
def x() {
a
}
}
What is the purpose of runtime mixins in groovy?
Mixins overall one of the ways to add functionallity to class without multiple inheritance issues. But what is its purpose in Groovy? Traits can do the same.
Annotation #Mixin is considered deprecated at all. Will runtime mixins have the same fate one day?
Runtime mixins give us the ability to add methods to existed classes at runtime. The important part of the answer is "existed" and "runtime".
So, you can easily add new methods to any 3rd party library at runtime.
Actually, recently I found a case where using mixins helped me a lot.
String.metaClass {
invokeMethod {
String name, args ->
System.out.println "[$name] invokation with $args"
}
}
class GroovyInterceptableWrapper
implements GroovyInterceptable {
}
String.mixin(GroovyInterceptableWrapper)
Though again if I used there trait instead of class and then invoked withTraits I would have achieved the same result.
I have an annotation which adds some methods and default constructor to annotated class.
I have managed to create a gdsl, to enable autocompletion in idea for methods, but I'm stuck with constructor and documentation is very poor.
Does anyone have any ideas, how to do this?
Maybe I could find a solution, in existing gdsl, but I can't remember any Transformation, related to constructors. Maybe you can remind me of any of them.
def objectContext = context(ctype: "java.lang.Object")
contributor(objectContext) {
if (hasAnnotation("com.xseagullx.SomeAnnotation")) {
// Here I want to add constructor's declaration(with empty arg's)
// …
// And then my methods.
method name: 'someMethod', type: 'void', params: [:]
}
}
EDITED: OK, if it's as #jasp say, and there is no DSL construct for declaring Constructors, I'm still asking for a good documentation sources, other than JB's confluence page. Tutorials and other sources. I'm familiar with embedded dsl's for groovy, grails and gradle.
Need smth. more structured, if it's possible.
All function invocations inside of GroovyDSL are just calls to wrappers around internal IDEA's Program Structure Interface (PCI). However it doesn't cover all of PCI's abilities, including default constructors functionality I believe. One of an evidence for that is singletonTransform.gdsl, which is bundled into IDEA from 9 version and describes #Singleton AST transformation. Here is it's code:
contributor(context()) {
if (classType?.hasAnnotation("groovy.lang.Singleton")) {
property name: "instance",
type: classType?.getQualifiedName() ?: "java.lang.Object",
isStatic: true
}
}
As you can see it doesn't change a constructor and it's visibility, so IDEA will autocomplete this invalid code:
#Singleton class Foo {}
def foo = new Foo()
Futhermore GDSL that describes the semantics of GroovyDSL (which is actually the part of /plugins/groovy/resources/standardDsls/metaDsl.gdsl of IDEA sources) doesn't provide any ability for describing of constructors.
In this case I suggest you use newify transformation which allows you to describe targetClass.name method returning created instance.
I know this is a bit old, but I found myself looking for something similar.
The DSL you are looking for is
method params: [:], constructor: true although I don't understand why you'd need it; if a class doesn't declare any constructors doesn't IDEA always suggest the default one?
I would like to be able to use plain java-style implicit/explicit casting instead of asType overrides so that sources written in Java work properly. I've overridden asType on String similarly to the approach suggested in How to overload some Groovy Type conversion for avoiding try/catch of NumberFormatException? like:
oldAsType = String.metaClass.getMetaMethod("asType", [Class] as Class[])
String.metaClass.asType = {Class typ ->
if (Foo.class.isAssignableFrom(typ)) {
Foo.myCast(delegate)
} else {
oldAsType.invoke(delegate,typ)
}
}
I'd like all of these options to work:
// groovy
String barString
Foo foo = barString asType(Foo.class) // asType works but
Foo foo = barString // implicit cast fails
Foo foo = (Foo) barString // explicit cast fails
The latter two fail because groovy is using DefaultTypeTransformation.castToType, which doesn't attempt to invoke new Foo() unless the object to be cast is either one of a slew of special cases or is some sort of Collection type.
Note that the solution Can I override cast operator in Groovy? doesn't solve the issue because the code that is doing the casting is regular Java code that I cannot alter, at least not at the source code level. I'm hoping that there is either a secret hook into casting or a way to override the static castToType method (in a Java class, called by another Java class - which Can you use Groovy meta programming to override a private method on a Java class says is unsupported)... or some other clever approach I haven't thought of.
Edit: The question is about using Java-style casting syntax, essentially to use groovy facilities to add an autoboxing method. Groovy calls this mechanism "casting," for better or worse (see DefaultTypeTransformation.castToType as referenced above). In particular, I have replaced an enum with a resourced class and want to retain JSON serialization. Groovy's JSON package automatically un/marshals enum values of instance members to strings and I'm trying to make the replacement class serialize compatibly with a minimal changes to the source code.
Part of the problem here is you are confusing conversion with casting. Using the "as" operator is not the same thing as imposing a cast. They seem similar, but they serve separate purposes.
Foo foo = (Foo) barString
That doesn't say something like "create a Foo out of barString". That says "Declare a reference named foo, associate the static type Foo with that reference and then point that reference at the object on the heap that the reference barString currently points to.". Unlike languages like C++, Groovy and Java do not allow you to ever get in a situation where a reference points at an object that is of a type that is incompatible with the reference's type. If you ever got into a situation where a Foo reference was pointing to a String on the heap, that would represent a bug in the JVM. It cannot be done. You can come up with ways to create Foo objects out of String objects, but that isn't what the code above is about.
The answer appears to be "no". Absent a rewrite of the DefaultTypeTransformation.castToType to allow for this sort of metaprogramming, the implication is to use another implementation strategy or use a different language.
I mainly program in groovy, but occasionally it's too slow. So I write a separate .java class, and put the code that needs to run faster in a java method and call that java method from my groovy code.
This causes me to end up with two separate files and two separate classes. Is there any way I could embed a java method right into the groovy file, maybe marking it with an annotation to indicate that it is java?
This is the idea behind groovy++. Marking a class or method with the #Typed annotation will cause it to use static typing instead of dynamic typing, while still retaining a lot of goodness of groovy.
While not exactly java, typed groovy++ methods generally perform about the same as java would.
More information on groovy++ is available at: https://code.google.com/p/groovypptest/wiki/Welcome
You don't need to do anything special.
Just write the Java class behind the groovy class. 99% of all Java source is valid groovy source as well.
class GroovyClass {
def a;
def doSomething(x,y) { return x*y; }
}
class JavaClass {
SomeType someVar;
public JavaClass() { /* ... */ } // some contructor
public void doit(String a, int b) {} // full typed method, that is java
}
Groovy++ is somethign completely different.
The JavaClass needs to have everything fully typed to be "Java" however your problem can be solved far easyer if you just use types in the relevant groovy methods.
class AnotherGroovyClass {
// typed
public Result someMethod(SomeArg arg1, SomeOtherArg arg2) {
}
def someVariable; // untyped
}
If you think the lack of speed comes from the dynamic nature of groovy then just use full types at the relevant points.