On 29.03.2016 18:15, OC wrote:
[...]
> class AnyClassOfMine {
> def name
> }
>
> class DumbProxy {
> def server
> def propertyMissing(String name) {
> server."$name"
> }
> }
>
> def objects=[new AnyClassOfMine(name:"Direct"),new DumbProxy(server:new AnyClassOfMine(name:"Proxied"))]
> for (AnyClassOfMine o in objects) println "got $o.name"
> ===
>
> Alas, instead of working as expected, this fails with the aforementioned nonsensical
exception:
>
> ===
> got Direct
> Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object
'DumbProxy@73f43791' with class 'DumbProxy' to class 'AnyClassOfMine'
> ...
> ===
There are multiple ways to "solve" the problem, but I am afraid, they
will all look like workarounds to you... The traditional Java way would be:
interface InterfaceForAnyClassOfMine {
def getName()
}
class AnyClassOfMine implements InterfaceForAnyClassOfMine {
def name
}
class DumbProxy implements InterfaceForAnyClassOfMine {
InterfaceForAnyClassOfMine server
def getName() {
server.name
}
}
Then of course you would not use AnyClassOfMine as base, but
InterfaceForAnyClassOfMine. You can make this a little bit more easy
with @Delegate:
class DumbProxy {
@Delegate InterfaceForAnyClassOfMine server
}
@Delegate will add the implements clause for you, as well as any compile
time defined method of InterfaceForAnyClassOfMine... basically you safe
a few lines. But basically DumbProxy does not have anything to do with
AnyClassOfMine, so no runtime solution will really work here, if you
still want to base on static types at some place.
Using runtime traits I would come up with this version:
class AnyClassOfMine { def name }
trait DumbProxy {}
def objects=[new AnyClassOfMine(name:"Proxied") as DumbProxy]
for (DumbProxy o in objects) println "got $o.name"
I think the basic problem is that you have no multiple inheritance in
Java and only an inconsitent fraction of it in Groovy. So on the JVM I
cannot make a class that implements a class AnyClassOfMine and DumbProxy
at the same time. I can do such things with interfaces though. This
again forces people to split their classes in interfaces and
implementations, both being first class citizens. Objective C is much
more flexible here. But it means I cannot apply the same concept to the
JVM world... not if I want to stay with the Java class model. Our traits
are kind of a hybrid, as they define multiple classes, one interface and
a specific implementation. Only because of that I can make a proxy here
and only of an interface. Dynamically generating a subclass is also
possible, and we actually do that as well in Groovy. But once you have
two super classes you are lost... especially without the magic
-forwardingTargetForSelector:(SEL)sel { return self.server; }
bye Jochen
|