First off: I absolutely LOVE Project Lombok. Awesome tool! There's so many excellent aspects to this 'compile time' library.
Loving the @ExtensionMethods, I have already hit this 'feature' a few times, so now it's time for me to ask this question:
Suppose I have the following classes:
@UtilityClass
public class AObject {
static public String message(final Object pObject) {
return "AObject = " + (pObject != null);
}
}
@UtilityClass
public class AString {
static public String message(final String pObject) {
return "AString = " + (pObject != null);
}
}
@ExtensionMethod({ AObject.class, AString.class })
public class Run_Object_String {
public static void main(final String[] args) {
System.out.println("\nRun_Object_String.main()");
final String s = "Bier!";
final Object o = new Object();
System.out.println("Testing s: " + s.message());
System.out.println("Testing o: " + o.message());
System.out.println("Testing s: " + s.message());
}
}
@ExtensionMethod({ AString.class, AObject.class })
public class Run_String_Object {
public static void main(final String[] args) {
System.out.println("\nRun_String_Object.main()");
final String s = "Bier!";
final Object o = new Object();
System.out.println("Testing s: " + s.message());
System.out.println("Testing o: " + o.message());
System.out.println("Testing s: " + s.message());
}
}
public class ClassPrevalenceTest {
public static void main(final String[] args) {
Run_Object_String.main(args);
Run_String_Object.main(args);
}
}
With the output:
Run_Object_String.main()
Testing s: AObject = true
Testing o: AObject = true
Testing s: AObject = true
Run_String_Object.main()
Testing s: AString = true
Testing o: AObject = true
Testing s: AString = true
- Why is this?
- Why is the
message(String)not called in the first example, even though it has a better method signature fit thanmessage(Object)? - Why is
@ExtensionMethoddependent on sequence of the arguments?
Here's what I blindly assume:
- when parsing for ExtensionMethods, Lombok will process annotation values from left to right
-
- For
Run_Object_Stringthat means: firstAObject, thenAString
- For
-
- For
Run_String_Objectthat means: firstAString, thenAObject
- For
- Object-String: When patching
AObjectinto classRun_Object_String, themessage(Object)method will be added. And when patching inAStringwith themessage(String)method, it will not be added. Presumably because themessage(Object)also matches a call tomessage(String), somessage(String)will not be added. - String-Object: When patching
AStringinto classRun_String_Object, themessage(String)method will be added. When patching inAObjectclass withmessage(Object), the old and presentmessage(String)method will NOT accept the callmessage(Object), thus the methodmessage(Object)will be added.
So, apart from taking great care of what order I add the @UtilityClass references, are there any other solutions to this?
- Can the Lombok preprocessor be extended and made more sensible when adding in extension methods?
- Do you guys have any suggestions regarding this, or an explanation of what is really happening (as opposed to my assumptions)