-1

I would like to be able to use plain java-style implicit/explicit casting instead of asType overrides so that sources written in Java work properly. I've overridden asType on String similarly to the approach suggested in How to overload some Groovy Type conversion for avoiding try/catch of NumberFormatException? like:

oldAsType = String.metaClass.getMetaMethod("asType", [Class] as Class[])
String.metaClass.asType = {Class typ ->
    if (Foo.class.isAssignableFrom(typ)) {
        Foo.myCast(delegate)
    } else {
        oldAsType.invoke(delegate,typ)
    }
}

I'd like all of these options to work:

// groovy
String barString
Foo foo = barString asType(Foo.class)  // asType works but
Foo foo = barString           // implicit cast fails
Foo foo = (Foo) barString     // explicit cast fails

The latter two fail because groovy is using DefaultTypeTransformation.castToType, which doesn't attempt to invoke new Foo() unless the object to be cast is either one of a slew of special cases or is some sort of Collection type.

Note that the solution Can I override cast operator in Groovy? doesn't solve the issue because the code that is doing the casting is regular Java code that I cannot alter, at least not at the source code level. I'm hoping that there is either a secret hook into casting or a way to override the static castToType method (in a Java class, called by another Java class - which Can you use Groovy meta programming to override a private method on a Java class says is unsupported)... or some other clever approach I haven't thought of.

Edit: The question is about using Java-style casting syntax, essentially to use groovy facilities to add an autoboxing method. Groovy calls this mechanism "casting," for better or worse (see DefaultTypeTransformation.castToType as referenced above). In particular, I have replaced an enum with a resourced class and want to retain JSON serialization. Groovy's JSON package automatically un/marshals enum values of instance members to strings and I'm trying to make the replacement class serialize compatibly with a minimal changes to the source code.

Community
  • 1
  • 1
m.thome
  • 222
  • 1
  • 6
  • 1
    What do you mean by "in a Java class, called by another Java class"? When a Java class calls another Java class, the Groovy runtime isn't involved, so none of this will work. Groovy metaprogramming only takes effect when the caller is a Groovy class. – Peter Niederwieser May 10 '14 at 00:58
  • Well, yes - that is why I said it is unsupported and why I'm looking for alternatives. The disappointing thing is both of the Java classes in question are part of the Groovy runtime which happen to be implemented in plain Java and without the hooks needed to (for instance) defer to asType overrides. There is even a comment in DefaultTypeTransformation.castToType that suggest the developers are aware of the issue - as is, the method it is a nasty pile of special case logic. – m.thome May 12 '14 at 14:10

2 Answers2

0

Part of the problem here is you are confusing conversion with casting. Using the "as" operator is not the same thing as imposing a cast. They seem similar, but they serve separate purposes.

Foo foo = (Foo) barString 

That doesn't say something like "create a Foo out of barString". That says "Declare a reference named foo, associate the static type Foo with that reference and then point that reference at the object on the heap that the reference barString currently points to.". Unlike languages like C++, Groovy and Java do not allow you to ever get in a situation where a reference points at an object that is of a type that is incompatible with the reference's type. If you ever got into a situation where a Foo reference was pointing to a String on the heap, that would represent a bug in the JVM. It cannot be done. You can come up with ways to create Foo objects out of String objects, but that isn't what the code above is about.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • No: the question is about syntax, not C-like pointer retyping or even Java class downcasting. Groovy explicitly supports several varieties of type conversions including, but not limited to, conversion of maps to objects and Strings to Enums. Even Java supports type conversion using both explicit and implicit casting syntax in limited situations via autoboxing: int to Integer (and back), numeric promotion, etc. I've edited my question to make more clear what I'm looking for. – m.thome May 12 '14 at 13:47
0

The answer appears to be "no". Absent a rewrite of the DefaultTypeTransformation.castToType to allow for this sort of metaprogramming, the implication is to use another implementation strategy or use a different language.

m.thome
  • 222
  • 1
  • 6