Suppose I have this class:
class MyClass {
int myInt
MyClass(myInt) {
this.myInt = myInt
}
def myMethod() {
print this.myInt
}
}
And somewhere I have:
def myClass1 = new MyClass(1)
def myMethodClosure = myClass1.&myMethod
def myClass2 = new MyClass(2)
Now if I call myMethodClosure() it will call myMethod() on myClass1 instance which will print 1. What I want is to call the same myMethodClosure but on a different instance, in this case on myClass2 so it can print 2. Is this possible?
I have tried using setDelegate(), but it does not work. I have also seen that there is field thisObject inside the closure class, but it does not have a setter, only a getter.
There were two methods added to Groovy to aid serialization of Closures, dehydrate and rehydrate. Basically, they strip (and reconstruct) a Closure's owner, thisObject and delegate. In this example, you could do:
myMethodClosure.rehydrate( myClass2, myClass2, myClass2 )()
To get the output 2, however I'd be wary about doing this as it is not what the method was intended for and there could be serious unforeseen consequences.
A better solution would probably be to write a factory method that gets a method reference for the given instance of MyClass. There may be other -- better -- solutions, but it depends on the situation you are in (that I suspect is not shown by the example in the question)
I believe closure "includes" the enclosing object to act upon. It is not possible override "this" inside a closure at runtime.
Related
I have a superclass called A and a subclass called B that inherits from A. The superclass's constructor looks like this:
A(String name, char displayChar, int hitPoints, Behaviour behaviour)
{
this.name = name;
this.displayChar = displayChar;
this.hitPoints = hitPoints
addBehaviour(behaviour);
}
A has attributes of name, displayChar, hitPoints, behaviour and has a method that calls addBehaviour which adds the behaviour to the object.
The subclass, B's constructor looks like this:
B(String name) {super(name, char 'b', 10, new WalkBehaviour()); }
Now my question is, does subclass B have an attribute of WalkBehaviour?
How would the UML diagram look like for this scenario? I know B inherits from A and A has Behaviour but does B has WalkBehaviour in this case? Since B doesn't have an instance variable of type WalkBehaviour in its class but only passes WalkBehaviour through its superclass's constructor.
does subclass B have an attribute of WalkBehaviour?
No. There is none declared. The superclass will do something with that new object but obviously it's hidden in the mist of its implementation.
Inheritance is nothing that involves multiple object creation. Your B instance is just a single one which does have attributes and operations like its super class.
Thus, in a SD, you will see only one life line for B:
As you can see the B instance will just issue a self-call to the super class's constructor.
Note: as #AxelScheithauer pointed out in the comment the super class will invoke addBehavior which can (but must not) be shown in the SD:
I have a Closure defined in a groovy file that load with the shell.evaluate() method.
I need to call this closure in by calling program using the shell."$closurename".call(arguments) call.
However to formulate the closure parameters ( argument above) I'd need to now what are the arguments and arguments names that the closure $Closurename accepts. Is there a way of dynamically knowing this in Groovy? I checked in the metaClass.method property but this does not work in my example below.
Below is the example code.
def arguments;
shell.evaluate(new File("/tmp/myGroovyClosureFile.groovy"))
testBlock = "myClosureName"
//Code here to find the parameters for myClosureName and create
//the arguments variable
shell."$testBlock".call(arguments)
As Jeff mentioned, it seems like groovy when generating code for closures anonymizes somehow the parameter names. However, you can still use reflection to get as much information as you can:
def cl = { int a, String b ->
println(a)
println(b)
}
def callMethod = cl.class.methods.find {
it.name == "call"
}
println callMethod.parameterTypes
println callMethod.parameters.name
and outputs:
[int, class java.lang.String]
[arg0, arg1]
Is there a way of dynamically knowing this in Groovy?
You can't really do it dynamically at runtime.
Here is a very beginner's question:
The class that I mock, has methods Map<String, Integer>methodA(String p1,String p2,String p3, SomeClass p4) and MyClass methodB(String p1,String p2,String p3)
methodA internally calls methodB:
Map<String, Integer> methodA(String p1, String p2, String p3, SomeClass p4){
MyClass data = methodB(p1,p2,p3);
.... do something
... return Map.
}
I am stubbing the methodB.
when(mockedTestClass.methodB(p1, p2, p3, null)).thenReturn(myData);
I use null for the fourth argument since SomeClass is an abstract class.
When I call the stubbed method in the test directly with p1, p2 p3 and null (p4) arguments, it returns the correct mock data (an instance of MyClass).
However, if I call methodA, it seems that methodB is not getting called and I get empty Map (not null) returned.
What would cause this?
Thank you in advance,
Yuri.
If I understand correctly, you have a class you're mocking, ClassA, that has two methods, method1 and method2. And you know that ClassA.method1 happens to call method2 internally. And so you've only mocked method2, and left method1 with the default behavior, right?
So in that case, both methods are actually mocked, you're mocking at the class level not the method level. When you do a when you're saying, "I want this method to return this exact result in this specific case. If you don't use when then the method is an empty mock returning a null or empty value for the type that it returns. It's assumed if you don't specify you don't care.
So given that, you should see that method1 when the class is mocked does not actually call method2. Both methods are mocked and only a direct call to method2 will return the result of your when matcher.
Also, when is used to ensure a specific result is returned when a method is called. If you want to verify that a certain method was actually called with specific parameters, you can do that like this:
verify(mockedClass).someMethod(p1, p2, p3, null); // <- or use matchers for the parameters
Groovy supports both default, and named arguments. I just dont see them working together.
I need some classes to support construction using simple non named arguments, and using named arguments like below:
def a1 = new A(2)
def a2 = new A(a: 200, b: "non default")
class A extends SomeBase {
def props
A(a=1, b="str") {
_init(a, b)
}
A(args) {
// use the values in the args map:
_init(args.a, args.b)
props = args
}
private _init(a, b) {
}
}
Is it generally good practice to support both at the same time? Is the above code the only way to it?
The given code will cause some problems. In particular, it'll generate two constructors with a single Object parameter. The first constructor generates bytecode equivalent to:
A() // a,b both default
A(Object) // a set, b default
A(Object, Object) // pass in both
The second generates this:
A(Object) // accepts any object
You can get around this problem by adding some types. Even though groovy has dynamic typing, the type declarations in methods and constructors still matter. For example:
A(int a = 1, String b = "str") { ... }
A(Map args) { ... }
As for good practices, I'd simply use one of the groovy.transform.Canonical or groovy.transform.TupleConstructor annotations. They will provide correct property map and positional parameter constructors automatically. TupleConstructor provides the constructors only, Canonical applies some other best practices with regards to equals, hashCode, and toString.
Say I have a function
def method1(MyClass2 mc2) {...}
and I call it with an object of type MyClass1. Is there a way that I can specify how to implicitly convert from MyClass1 to MyClass2, so that the method call will work without having to explicitly say method1(mc1 as MyClass2)?
If MyClass1 doesn't implement/extend MyClass2, there isn't anything that I'm aware of that'll do the "as MyClass2" conversion without the old standby Java method overloading. Explicitly overloading the method with the signature including MyClass1:
def method1(MyClass1 mc1) {
method1(mc1 as MyClass2)
}
The other, more groovy, alternative is to not explicitly type method1 so that it doesn't demand that you have an instance of MyClass2:
def method1(mc) {
// do stuff and let mc walk/talk/quack like MyClass2
// or even do the "as MyClass2" in this method if you need it for something further down.
}