Groovy seems to be unable to compile a class where I've derived from a Generic base class and overloaded a method returning a generic array. The same example in Java appears to compile correctly, which is surprising as I expected Groovy to have source-level compatibility [ref].
This can be reproduced with the following adapter example. This example can also be executed online at the awesome Groovy Web Console.
class Person {}
abstract class BaseAdapter<T> {
public T[] getAll() {
return getAllInternal();
}
protected abstract T[] getAllInternal()
}
class PersonAdapter extends BaseAdapter<Person> {
protected Person[] getAllInternal() {
return new Person[0];
}
}
Compiling this produces the message:
Script1.groovy: 12: The return type of Person[] getAllInternal() in PersonAdapter is incompatible with [Ljava.lang.Object; getAllInternal() in BaseAdapter
. At [12:5] # line 12, column 5.
protected Person[] getAllInternal() {
^
1 error
Have I got the syntax incorrect? Or, is this a Groovy issue?
I expected Groovy to have source-level compatibility.
The source-level compatibility is maybe 90% but not perfect (nor is this a goal).
Have I got the syntax incorrect? Or, is this a Groovy issue?
Probably a bug. Please file a bug report.
Related
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()
package bug
import groovy.transform.CompileStatic
#CompileStatic
class BugCheck
{
static void main(String[] args)
{
new BugCheck()
}
BugCheck()
{
new Child().method(1f) // causes the problem
}
class Parent
{
void method(float f, boolean b=true)
{
println("Parent")
}
}
class Child extends Parent
{
#Override
void method(float f)
{
println("Child")
}
}
}
Compiling this piece of code with Groovy 2.3.4 leads to the following error:
/mirror/dev/Groovy/src/bug/BugCheck.groovy: 17: [Static type checking] - Reference to method is ambiguous. Cannot choose between [void bug.BugCheck$Child#method(float), void bug.BugCheck$Child#method(float)]
Is this a bug in Groovy, or do I miss something here?
The method signatures vary, but since the Parent method has a default value, calling it with no boolean value creates an ambiguity: do you mean the Child method with no parameter, or the parent with a default boolean?
If Child declares a method with the exact same signature the ambiguity is resolved.
From a language design (or usage?) standpoint this is pretty shaky reasoning, though; IMO the Child method should be called if no boolean is provided. IMO the confusion is warranted.
I've created my project in vs2008.It works fine.But when i opened the solution and try to build it in vs2012 i am getting the following error in TransactionDB.dbml page.
a partial method may not have multiple defining declarations
What could be the problem??
.net supports partial methods.
It means you write a definition in one part of the partial class and the implementation in another. Like this:
partial class MyClass
{
partial void MyPartialMethod(string s);
}
// This part can be in a separate file.
partial class MyClass
{
// Comment out this method and the program will still compile.
partial void MyPartialMethod(string s)
{
Console.WriteLine("Something happened: {0}", s);
}
}
In your case I you have the two definitions of the partial method causing the compiler to fail.
Source MSDN
The defining declaration of a partial method is the part that specifies the method signature, but not the implementation (method body). A partial method must have exactly one defining declaration for each unique signature. Each overloaded version of a partial method must have its own defining declaration.
To correct this error
Remove all except one defining declaration for the partial method.
Example
// cs0756.cs
using System;
public partial class C
{
partial void Part();
partial void Part(); // CS0756
public static int Main()
{
return 1;
}
}
I'm trying to use Groovy #groovy.transform.Immutable to implement classes with properties of unsupported "immutable" types. In my case it is java.io.File
For example, having class like
#groovy.transform.Immutable class TwoFiles {
File file1,file2
}
gives me following compile error
Groovyc: #Immutable processor doesn't know how to handle field 'file1' of type 'java.io.File' while compiling class TwoFiles.
#Immutable classes only support properties with effectively immutable types including:
- Strings, primitive types, wrapper types, BigInteger and BigDecimal, enums
- other #Immutable classes and known immutables (java.awt.Color, java.net.URI)
- Cloneable classes, collections, maps and arrays, and other classes with special handling (java.util.Date)
Other restrictions apply, please see the groovydoc for #Immutable for further details
One option I found it to extend java.io.File to make it Cloneable but I'm not happy with this solution. Following code compiles and works, but having own subclass of java.io.File is not what I'd like.
#groovy.transform.Immutable class TwoCloneableFiles {
FileCloneable file1,file2
class FileCloneable extends File implements Cloneable{
FileCloneable(String s) {
super(s)
}
// ... and other constructors ...
}
}
So my question is: Is there any other option how to use java.io.File directly in such class?
Possibly to mark java.io.File as "known immutable" for the purpose of #groovy.transform.Immutable (same as it seems to be done for java.awt.Color, java.net.URI)?
Have you tried using knownImmutableClasses to specify File? Something like this should work:
#groovy.transform.Immutable(knownImmutableClasses = [File])
class TwoFiles {
File file1,file2
}
(With File, you could probably also get rougly the effect you want with the following:
#groovy.transform.Immutable
class TwoFiles {
String file1,file2
public File getFile1() {return new File(file1)}
public File getFile2() {return new File(file2)}
}
def f = new TwoFiles("/", "/Users")
assert f.file1.class == File
)
I am trying to override the functionality of a method of a java type instance in my Groovy code but I am getting a classcast exception.
I looked at the guide posted here but I can not get it to work.
Since my actual problem is a bit of mess, below is some runnable example code that fails with the same error.
In the example I want to override the substring method of an instance of the java.lang.String class. In reality I want to override a method of an instance of a class that does not have a corresponding Groovy implementation, so the answer to my example is not to simply use a Groovy string instance.
class example {
static void main(args) {
java.lang.String hey = new java.lang.String("hey")
ExpandoMetaClass emc = new ExpandoMetaClass( java.lang.String, false )
emc.substring = {
"This is not a very good substring implementation"
}
emc.initialize()
def proxiedHey = new groovy.util.Proxy().wrap(hey)
proxiedHey.setMetaClass(emc)
printf proxiedHey.toString()
printf proxiedHey.substring(1)
}
}
The above example fails at line 12, i.e printf meh.toString(). The exception thrown is
Caught: java.lang.ClassCastException:
groovy.util.Proxy cannot be cast to
java.lang.CharSequence at
example.main(test.groovy:12)
So, any ideas on what I am doing wrong or if there is another way to solve my problem of adding and/or overriding methods of a java type instance?
I am using Groovy version 1.7.4.
You are creating an ExpandoMetaClass for java.lang.String, but assigning it to a groovy.util.Proxy. Make a metaClass for groovy.util.Proxy instread, like so:
java.lang.String hey = new java.lang.String("hey")
def proxiedHey = new groovy.util.Proxy().wrap(hey)
ExpandoMetaClass emc = new ExpandoMetaClass( groovy.util.Proxy, false )
emc.substring = {
"This is not a very good substring implementation"
}
emc.initialize()
proxiedHey.setMetaClass(emc)
printf proxiedHey.toString()
printf proxiedHey.substring(1)
Have you looked at Pimp my Library Pattern which allows you to add using Groovy Categories. You might find it more convenient and easy to understand in your case.
#Category(String)
class StringSubstrCategory {
def substring( int n) {
"This is not a very good substring implementation"
}
}
use (StringSubstrCategory) {
"hey".substring(1)
}