Groovy: Inherit trait method - groovy

So I have the following case:
trait JsonRepresentable {
def foo() { print "json" }
}
class SuperA implements JsonRepresentable { }
class SuperB implements JsonRepresentable { }
class Child1 extends SuperA {}
class Child2 extends SuperB { }
Now, if I call the foo() method on SuperA or SuperB it works fine. However if I inherit from them the foo() method is not implemented on the child classes.
Groovy:Can't have an abstract method in a non-abstract class. The class 'Child1' must be declared abstract or the method 'foo()' must be implemented.
It can be solved if I implement the JsonRepresentable trait on the child too, but its already defined on the super class so I guess there is a way to inherit the trait's foo method some way. Can you help me how to do that?
Edit:
Groovy version: 2.3.10

The problem was not in groovy. It was the eclipse groovy plugin (or compiler) which marked the build erroneously. I couldn't solve the compilation issue, but it runs fine when I start the application, so it's ok with me.

Related

How to reference subclass from a static superclass method in Groovy

A simplified version of what I'm trying to do in Groovy:
class Animal {
static def echo() {
println this.name // ie "class.name"
}
}
class Dog extends Animal {
}
class Cat extends Animal {
}
Dog.echo()
Cat.echo()
// Output:
// => Animal
// => Animal
//
// What I want:
// => Dog
// => Cat
I think what I'm asking here is: when I call a static method on an object, and
the static method is defined in the object's superclass, is there a way to obtain
the actual type of the object?
A static method is not defined in the object context, but in the class context. You might get confused by the presence of this in the Groovy static method. However, it's only a syntactic sugar that eventually replaces this.name with Animal.class.name.
If you compile the Animal class from your example with a static compilation enabled, you will see that it compiles to the following Java equivalent (result after decompiling the .class file):
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
public class Animal implements GroovyObject {
public Animal() {
MetaClass var1 = this.$getStaticMetaClass();
this.metaClass = var1;
}
public static Object echo() {
DefaultGroovyMethods.println(Animal.class, Animal.class.getName());
return null;
}
}
You can see that the following line in the echo method:
DefaultGroovyMethods.println(Animal.class, Animal.class.getName());
operates directly on the Animal class name. So from the echo method perspective, it doesn't matter how many classes extend it. As long as those classes invoke echo method defined in the Animal class, you will always see Animal printed as a result.
And there is even more than that. If you use the following compiler configuration script:
config.groovy
withConfig(configuration) {
ast(groovy.transform.CompileStatic)
ast(groovy.transform.TypeChecked)
}
and then compile the script (let's call it script.groovy) using this configuration option with the following command:
groovyc --configscript=config.groovy script.groovy
then you will see something like this after decompiling the .class file:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import org.codehaus.groovy.runtime.InvokerHelper;
public class script extends groovy.lang.Script {
public script() {
}
public script(Binding context) {
super(context);
}
public static void main(String... args) {
InvokerHelper.runScript(script.class, args);
}
public Object run() {
Animal.echo();
return Animal.echo();
}
}
You can see that even though you have invoked Dog.echo() and Cat.echo() in your Groovy script, the compiler replaced these calls with the double Animal.echo() invocation. It happened because calling this static method on any other subclass does not make any difference.
Possible solution: applying double dispatch
There is one way to get the expected output - override echo static method in Dog and Cat class. I can assume that your real method may do something more than the exemplary echo method you have shown above, so you might need to call the super echo method from a parent class. But... there are two problems: (1) you can't use super.echo() in the static context, and (2) it doesn't solve the problem, because parent method still operates in the Animal class context.'
To solve this kind of issue you might want to mimic a technique called double dispatch. In short - when we don't have information about the caller in the method that was called, let's allow the caller to pass this information with the method call. Consider the following example:
import groovy.transform.CompileStatic
#CompileStatic
class Animal {
// This is a replacement for the previous echo() method - this one knows the animal type from a parameter
protected static void echo(Class<? extends Animal> clazz) {
println clazz.name
}
static void echo() {
echo(Animal)
}
}
#CompileStatic
class Dog extends Animal {
static void echo() {
echo(Dog)
}
}
#CompileStatic
class Cat extends Animal {
static void echo() {
echo(Cat)
}
}
Animal.echo()
Dog.echo()
Cat.echo()
This may sound like a boilerplate solution - it requires implementing echo method in each subclass. However, it encapsulates the echo logic in the method that requires Class<? extends Animal> parameter, so we can let every subclass to introduce their concrete subtype. Of course, this is not a perfect solution. It requires implementing echo method in each subclass, but there is no other alternative way. Another problem is that it doesn't stop you from calling Dog.echo(Animal) which will cause the same effect as calling Animal.echo(). This double dispatch like approach is more like introducing a shorthand version of echo method which uses the common static echo method implementation for simplicity.
I don't know if this kind of approach solves your problem, but maybe it will help you find a final solution.

Groovy class extends parent implements interface, parent implements method in interface, overide error

Easier to explain with simplified code. I have the following interface
interface FooInterface{
public void foo()
}
I have the following JAVA parent class from a library (notice the final keyword):
class Parent {
public final foo()
}
Finally, the child class:
class Child extends Parent implement FooInterface{
}
This results in compilation error that I cannot override the final parent method in the child class, which technically I am not. I figure this is a groovyism I'm not familiar with. So my question are:
Why does the compiler think I'm overriding?
How can I get this to compile?
can't reproduce
final method:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html#get()
works fine in groovy 2.4.5
import java.util.concurrent.atomic.AtomicBoolean;
interface I{
public boolean get();
}
public class B extends AtomicBoolean implements I{
}
def b=new B()

Parameter specified as non-null is null when using Mokito anyObject() on Kotlin function

My code as below, refering to the solution in https://stackoverflow.com/a/30308199/3286489
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.Mockito.*
class SimpleClassTest {
private fun <T> anyObject(): T {
Mockito.anyObject<T>()
return uninitialized()
}
private fun <T> uninitialized(): T = null as T
lateinit var simpleObject: SimpleClass
#Mock lateinit var injectedObject: InjectedClass
#Before
fun setUp() {
MockitoAnnotations.initMocks(this)
}
#Test
fun testSimpleFunction() {
simpleObject = SimpleClass(injectedObject)
verify(injectedObject).settingDependentObject(anyObject())
}
}
I still have the below error
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method my.package.InjectedClass.settingDependentObject, parameter dependentObject
Did I miss anything?
UPDATED
Below is the code tested (simplest form and working)
class SimpleClass(val injectedClass: InjectedClass) {
fun simpleFunction() {
injectedClass.settingDependentObject(DependentClass(Response.Builder().build()))
}
}
open class DependentClass(response: Response) {
}
open class InjectedClass() {
lateinit var dependentObject: DependentClass
fun settingDependentObject(dependentObject: DependentClass) {
this.dependentObject = dependentObject
}
}
By default Kotlin classes and members are final. Mockito cannot mock final classes or methods.
Thus when you write:
verify(injectedObject).settingDependentObject(anyObject())
the real implementation is called which requires non null argument.
To fix that either open your class and method or, even better, change SimpleClass to accept an interface as its constructor argument and mock the interface instead.
There is a project specifically to help deal with Kotlin "closed by default" in unit testing with Mockito. For JUNIT, you can use the kotlin-testrunner which is an easy way to make any Kotlin test automatically open up classes for testing as they are loaded by the classloader. Usage is simple, just add one annotation of #RunWith(KotlinTestRunner::class), for example:
#RunWith(KotlinTestRunner::class)
class MyKotlinTestclass {
#Test
fun test() {
...
}
}
This is thoroughly covered in the article Never say final: mocking Kotlin classes in unit tests
This covers your use case in an automatic way by allowing all classes to be mocked that otherwise would not be allowed.
I ran into the same issue with Mockito when using RETURNS_DEEP_STUBS. It seems like nulls are still returned for nested objects, even when using the kotlin-allopen plugin.
Please check out and comment on this issue on Mockito if you're having the same problem.
You can use this function instead
inline fun <reified T : Any> any(): T = Mockito.any(T::class.java) ?: T::class.java.newInstance()

How to call a super constructor in groovy that accepts varargs?

I am using groovy as an extension language in my application. The constructor of the class which a script extend accepts variable arguments. When I try to instantiate the groovy class, I get an java.lang.ArrayIndexOutOfBoundsException from the super() call in the constructor. The issue can easily be reproduced in a standalone groovy script:
// problem.groovy
class A {
A(float ... more) {}
}
class B extends A {
B() {
super();
}
}
new B();
when run, this produces:
$ groovy problem.groovy
Caught: java.lang.ArrayIndexOutOfBoundsException: 0
java.lang.ArrayIndexOutOfBoundsException: 0
at B.<init>(problem.groovy:7)
at problem.run(problem.groovy:11)
line 7 is the super() call in class B.
Is this a bug in the language itself? I couldn't find any other mention of it online. I'm new to Groovy and I may well not be understanding some subtlety of the language. At the very least, it seems like this should throw a compiler error when loading the script.
You can use #InheritConstructors AST to avoid this boilerplate code.
class A {
A(float ... more) {}
}
#groovy.transform.InheritConstructors
class B extends A {}
new B()
Moreover, in your example wouldn't you provide a default constructor in A (since it is being overloaded) and then use super() in B's constructor. Or initialize the overloaded constructors args to null.
class A {
A(){println 'default'}
//Or use A(float... more = null) {println 'varargs'}
//instead of default constructor
A(float... more) {println 'varargs'}
}
class B extends A {
B(){
super()
}
}
new B()
//Uses default constructor A() if overloaded
//constructor is not initialized to null
It seems to be calling a nonexistent constructor with super() - call it even with a null or put a no arg constructor in A and it works.
It appears that the variable arg constructor on the superclass isn't matching. Fun.

Groovy: How to get Type on which a static method is called?

When a static method defined on Base class is called using Child class, How to find it was called on Child class type?:
class Base {
static def method(){
println "class on which this method is called? ${this}"
}
}
class Child extends Base {}
Child.method()
In the code above, this rightly points to the Base class.
I don't think it can be done with actual static methods, but a nice alternative is to use the groovy expandoMetaClass to add a static closure method. Inside said closure, you can access the calling class as delegate. I.e.
Base.metaClass.static.anotherMethod = {
println "class on which another method is called? ${delegate}"
}
Calling now Base.anotherMethod() will have delegate referring to Base and calling Child.anotherMethod will have it pointing to Child.

Resources