groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jochen Theodorou <blackd...@gmx.org>
Subject Re: Proxying how to?!?
Date Wed, 30 Mar 2016 15:12:32 GMT


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

Mime
View raw message