I'd like to see how this Java code would look in JRuby:
ParseQuery query = new ParseQuery("MyClass");
query.getInBackground(myId, new GetCallback() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
objectWasRetrievedSuccessfully(object);
} else {
objectRetrievalFailed();
}
}
});
The biggest part of confusion for me is the anonymous inner class. This is my best first guess:
query = ParseQuery.new("GameScore")
query.getInBackground("xWMyZ4YEGZ", Class.new(GetCallback) do
def done(object, e)
# ...
end
end.new)
Update: Edited based on this: http://www.ruby-forum.com/topic/188599#823271
The syntax for expressing this in JRuby is deceptively simple. JRuby has a feature called 'closure conversion' where a closure passed to a method can is converted into the appropriate Java interface. From the JRuby docs:
This not only works for event listeners or Runnable, but basically for any interface. When calling a method that expects an interface, JRuby checks if a block is passed and automatically converts the block to an object implementing the interface.
So, your code would look like:
query.in_background 'xWMyZ4YEGZ' { |object, e|
# do stuff
}
The 'calling Java from JRuby' page on the JRuby wiki is a good resource for problems like these.
Related
I'm very new to Java so it makes it hard for me to explain what I'm trying to do.
I have an abstract class that invokes several object constants like this:
public abstract class Enchantment implements Keyed {
/**
* Provides protection against environmental damage
*/
public static final Enchantment PROTECTION_ENVIRONMENTAL = new EnchantmentWrapper("protection");
In a different file I can access this perfectly fine with Enchantment value = Enchantment.PROTECTION_ENVIRONMENTAL;
However, I'm trying to use a string variable for this instead. Something like this:
String str = "PROTECTION_ENVIRONMENTAL";
Enchantment value = Enchantment.str;
Obviously that won't work. So I did a bunch of research and learned I need to use reflection for this. Using this source code's docs I figured I was looking for field data. So I tried both:
Field fld = Enchantment.class.getField("PROTECTION_ENVIRONMENTAL");
Field fld = Enchantment.class.getDeclaredField("PROTECTION_ENVIRONMENTAL");
But these returned me a NoSuchFieldException. As I was on it, I've tried both getMethod() and getDeclaredMethod() just as well equally with no luck.
I'm now at the point that these are probably "object constants"? I'm not sure how to call them. But I'm definitely at a loss on how to get this to work now and after everything I've tried myself, I figured it was time to ask for some help here.
That one comment is spot on: you absolutely do not use reflection here.
There are only two valid reasons to use reflection:
you are creating a framework that has to deal with classes it doesn't know about
you have for some other reason to deal with classes you don't know about at compile time
But your code perfectly knows about that Enchantment class, its capabilities, and so on. Therefore reflection is the wrong approach. You figured it yourself: it is damn hard to get right, and damn right to get it wrong in some subtle ways. And when you get it wrong, it always blows up at runtime. Reflection code compiling means nothing. It always waits for you to run it to throw up in your face.
So to answer your question by not answering it: use a Map. Like:
Map<String, Enchantment> enchantmentsByConstantName = new HashMap<>();
enchantmentsByConstantName.put("PROTECTION_ENVIRONMENTAL", PROTECTION_ENVIRONMENTAL);
Alternatively, these constants could go into an enum, as outlined in the other answer, but in a sightly different way:
enum EnchantmentHolder {
PROTECTION_ENVIRONMENTAL(new EnchantmentWrapper("protection")),
ANOTHER_ENCHANTMENT(...)
A_THIRD_ENCHANTMENT(...)
...;
private Enchantment enchantment;
private EnchantmentHolder(Enchantment enchantment) {
this.entchantment = entchantment;
}
public Enchantment getEntchantment() { return entchantment; }
You may want to look into enumerations if you know they're going to be constant values;
public enum Enchantment {
PROTECTION_ENVIRONMENTAL {
public void cast() {
// do enum-specific stuff here
}
},
ANOTHER_ENCHANTMENT {
public void cast() {
// do enum-specific stuff here
}
},
A_THIRD_ENCHANTMENT{
public void cast() {
// do enum-specific stuff here
}
};
public abstract void cast();
}
enums can be treated like classes and have methods and properties. You can also convert to and from strings Enchantment.valueOf("PROTECTION_ENVIRONMENTAL") but that's generally if you are reading from a configuration file - in code you'd reference the value directly.
Once you have the Field, you need to call Field.get(Object) with an instance (in this case the class). Something like,
Class<?> cls = Enchantment.class;
try {
Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
System.out.println(f.get(cls));
} catch (Exception e) {
e.printStackTrace();
}
Since you want the Enchantment, you could then test that the instance you get is assignable to Enchantment. Something like,
Class<? extends Enchantment> cls = Enchantment.class;
try {
Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
Object obj = f.get(cls);
if (cls.isAssignableFrom(obj.getClass())) {
Enchantment e = cls.cast(obj);
System.out.println(e);
}
} catch (Exception e) {
e.printStackTrace();
}
But the enum approach is better.
I have a kotlin web request method that takes a function as a parameter.
Due to how one of my classes is set up, I need to keep it as a java class but I need to call the web request method from the java class.
I have a class called Lock that I am fetching from my database using Fuel
My kotlin method is as follows
fun fetchLocks(completion: (Array<Lock>) -> Unit) {
// asynchronous api calls that aren't relevant.
completion(locks)
}
I know that this method works and am able to call it from a kotlin file
FuelHelper().fetchLocks { locks ->
Do stuff with my locks
}
The issue I am having is getting the proper syntax in order to call this method in java.
new FuelHelper().fetchLocks();
The parameter java expects is (Function1<?super Lock[], Unit>)
I have tried for a while now and am unable to get past this. Any help would be appreciated.
Assuming that you are using java 8 syntax.
new FuelHelper().fetchLocks(locks -> {
...
});
Or without lambda
new FuelHelper().fetchLocks(new Function1<Lock[], Unit>() {
#Override
public Unit invoke(Lock[] locks) {
return null;
}
});
It's exactly what it says - You have to pass an object implementing interface Function1 (source from generated file Functions.kt):
/** A function that takes 1 argument. */
public interface Function1<in P1, out R> : Function<R> {
/** Invokes the function with the specified argument. */
public operator fun invoke(p1: P1): R
}
In your case you create an anonymous class the same way you do for all small listeners like onClicks etc.:
new FuelHelper().fetchLocks(new Function1<Lock[], Unit>() {
#Override
public Unit invoke(Lock[] locks) {
// handle locks
return null;
}
});
I want to intercept all method calls for Script and any of its subtypes using MetaClasses preferably from Java but if needed I can do it from Groovy. I basically want to do something like this:
MetaClassImpl meta = new MetaClassImpl(Script.class) {
#Override
public final Object invokeMethod(Object obj, String method, Object[] args) {
if(method.equals("evaluate")) {
System.out.println("intercepted");
return run(shell, (String) args[0], "Evaluate");
} else {
return super.invokeMethod(obj, method, args);
}
}
};
The above works fine if I apply it to every instance of Script that I create but I'd like to apply it to the Script class and have it apply to all of its subtypes. Is there any way of doing this?
EDIT: What I'm attempting to do is replace evaluate with another method for all instances of Script and its subtypes. Either that or get evaluate to respect the ImportCustomizer set on the groovy shell the script is running inside of.
I have some code written in Java that uses Generics. This is a simple version:
// In Java
public interface Testable {
void test();
}
public class TestableImpl implements Testable {
#Override
public void test(){
System.out.println("hello");
}
}
public class Test {
public <T extends Testable> void runTest(Collection<T> ts){
System.out.println("Collection<T>");
for(T t: ts)
t.test();
}
public void runTest(Object o){
System.out.println("Object");
System.out.println(o);
}
}
// in Groovy - this is how I have to use the code
Test test = new Test()
test.runTest([new TestableImpl(), new TestableImpl()])
test.runTest([1,2,3]) //exception here
I am suprised that the second method call is dispatched to the wrong method (wrong in my Javish understanding). Instead calling the Object overload, the Collection gets called.
I am using Groovy 2.1.9, Windows 7.
And the exception is:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException:
Cannot cast object '1' with class 'java.lang.Integer' to class 'Testable'
org.codehaus.groovy.runtime.typehandling.GroovyCastException:
Cannot cast object '1' with class 'java.lang.Integer' to class 'Testable'
Why? How to solve this?
How to make Groovy call the same method as Java would?
edit: to further explain the case, I'd like to write a Spock test for it (just imagine the method returns something, say a String..):
def "good dispatch"(in,out) {
expect:
test.runTest(in) == out
where:
in | out
new Object() | "a value for Object"
new Integer(123) | "a value for Object"
[1,2,3] | "a value for Object"
[new TestableImpl()] | "a value for Testable Collection"
}
Others have suggested possible ways to solve your problem but here is WHY it happens.
Groovy - being a dynamic language - uses the runtime type information to invoke the correct method. Java, on the other hand, determines which method will be used based on the static type.
A simple example that demonstrates the differences between JAVA and GROOVY:
void foo(Collection coll) {
System.out.println("coll")
}
void foo(Object obj) {
System.out.println("obj")
}
In GROOVY:
Object x = [1,2,3] //dynamic type at invocation time will be ArrayList
foo(x)
//OUT: coll
In JAVA:
Object x = Arrays.asList(1,2,3);
foo(x);
//OUT: obj
Collection x = Arrays.asList(1,2,3);
foo(x);
//OUT: coll
Now in your example (it does not really have anything to do with the use of generics):
test.runTest([new TestableImpl(), ...]) //ArrayList --> collection method will be used
test.runTest([1,2,3]) //also ArrayList --> best match is the collection variant
If multiple dispatch is not what you want, can you cast the argument in the test script?
test.runTest( (Object) [1,2,3] )
This happens because Java strips the generic information from the code at compile time.
When Groovy tried to select the correct method at runtime, it gets an ArrayList as parameter for the second call (note: No generic information anymore) which matches runTest(Collection tx) better than runTest(Object o).
There are two ways to solve this:
Create two methods with different names
Delete runTest(Collection). Instead use instanceof in runTest(Object) to determine whether the argument is a collection of the correct type and delegate to a new internal method runTestsInCollection().
Lets start from the solution:
import groovy.transform.CompileStatic
import spock.lang.Specification
import spock.lang.Subject
class TestSpec extends Specification {
#Subject
Test test = new Test()
def 'Invokes proper method from JAVA class'() {
given:
List input = [1,2,3]
when:
invokeTestedMethodJavaWay(test, input)
then:
noExceptionThrown()
}
#CompileStatic
void invokeTestedMethodJavaWay(Test test, Object input) {
test.runTest(input)
}
}
First of all, you cannot override methods by generic type even in JAVA. For example if you try adding another method with same contract but overloaded with different generic type, let say public <P extends Printable> void runTest(Collection<P> ps) you will run into disambiguation problem as both methods will have same erasure.
What's more important in your question, has been already stated in other answers here. Your expectations didn't meet the behaviour as we are getting into compile vs runtime types evaluation between respectively JAVA and Groovy. This can be very useful if one is aware of this. For example when handling exceptions. Consider following example.
JAVA:
public void someMethod() {
try {
// some code possibly throwing different exceptions
} catch (SQLException e) {
// SQL handle
} catch (IllegalStateException e) {
// illegal state handle
} catch (RuntimeException e) {
// runtime handle
} catch (Exception e) {
// common handle
}
}
Groovy:
void someMethod() {
try {
// some code possibly throwing different exceptions
} catch (Exception e) {
handle(e)
}
}
void handle(Exception e) { /* common handle */ }
void handle(IllegalStateException e) { /* illegal state handle */ }
void handle(RuntimeException e) { /* runtime handle */ }
void handle(SQLException e) { /* SQL handle */ }
I find Groovy way much cleaner than nasty try-catch multi block, especially that you can implement all handle methods in separate object and delegate handling. So it's not a bug, it's a feature :)
Getting back to the solution. You cannot annotate whole Spock's test class with #CompileStatic as you already know. However you can do this with a single method (or separate helper class). This will bring back expected java-like behaviour (compile time type evaluation) for any call from within annotated method.
Hope this helped, cheers!
PS. #Subject annotation is only used for the sake of readability. It points which object is under test (is subject of the specification).
EDIT:
After some discussion with the author of the question, not so clean but working solution:
import groovy.transform.CompileStatic
import spock.lang.Specification
import spock.lang.Subject
class TestSpec extends Specification {
#Subject Test test = new Test()
TestInvoker invoker = new TestInvoker(test)
def 'Invokes proper method from JAVA class'() {
when:
invoker.invokeTestedMethod(input)
then:
noExceptionThrown()
where:
input << [
[1, 2, 3, 4, 5],
[new TestableImpl(), new TestableImpl()]
]
}
}
#CompileStatic
class TestInvoker {
Test target
TestInvoker(Test target) {
this.target = target
}
void invokeTestedMethod(Object input) {
target.runTest(input)
}
void invokeTestedMethod(Collection input) {
if (input.first() instanceof Testable) {
target.runTest(input)
} else {
this.invokeTestedMethod((Object) input)
}
}
}
If you would need to check by more than one generic type of collection, please notice that instanceof can be used in switch case statements in Groovy.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java method overloading + double dispatch
probably a dumb newbie question:. I want to avoid instanceof operator in situations like this:
class Service {
method(Some param) { }
}
class Special extends Some { }
class SpecialService extends Service {
method(Some param) {
if (param instanceof Special) {
//do special things
}
}
method(Special param) {
//do special things
}
}
Is the second special method the correct way to avoid the instanceof ?
Will there be any problems on the caller side of the service? In my case the special service is a customized version, plugged in and called from base code. Which method will be called?
Service s = new SpecialService();
s.method(specialparam);
And please point me to compact description or pattern how to solve this. Seems to be basic Java / OO knowledge...
Java does this automagically. Your code will work exactly as you want to, without the if statement. Java selects the most specific (most subclassed) method signature when choosing which version of the method to execute.
Here is a really good article on the subject.
I'm not sure durron597 is right. It all depends on how your code is written. It would workautomatically only if both variables are declared using specific types:
//good
Special specialparam = new Special();
SpecialService s = new SpecialService();
s.method(specialparam);
Code like
//bad
Some specialparam = new Special();
SpecialService s = new SpecialService();
s.method(specialparam);
or like
//bad
Special specialparam = new Special();
Service s = new SpecialService();
s.method(specialparam);
wouldn't work as you expect because known compile-time types are used to select method.
The whole design looks suspicously. This might be the right way but probably it is worths reconsidering it.
One of things that might hepl is Double dispatch mentioned by dasblinkenlight's comment. But to do one of base classes (Some or Service) should know about special cases. In short idea is that you write something like this:
class Some {
public void dispatch(Service service) {
service.method(this);
}
}
class Special extends Some {
public void dispatch(Service service) {
service.method(this);
}
}
class Service {
void dispatch(Some some) {
some.dispatch(this);
}
void method(Some some) {
// do common things here
}
void method(Special some) {
method((Some)some);
}
}
class SpecialService extends Service {
method(Special param) {
//do special things
}
}