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

Reply via email to