Greetings.

I'm not understanding proxies.  Can anyone advise me what I'm missing?

I try the following:

user=> (def m (proxy [java.util.HashMap] []
         (finalize []
           ;(proxy-super finalize)
           (prn "finalizing..."))
         (hashCode []
           99)))
#'user/m
user=> (.hashCode m)
99
user=> (.finalize m)
IllegalArgumentException No matching field found: finalize for class 
user.proxy$java.util.HashMap$0  clojure.lang.Reflector.getInstanceField 
(Reflector.java:289)
user=> (ancestors m)
nil
user=> 

(the 'proxy-super' is commented out, just to reassure myself that its presence 
is not somehow the root of the problem)

I'm afraid that the documentation of the 'proxy' macro is too terse for me to 
work out what's supposed to be happening here.

The documentation says that 'proxy' "creates a instance of a proxy class that 
implements the named class/interface(s) by calling the supplied fns."  That 
suggests (without quite saying so) that 'm' should be an extension of class 
java.util.HashMap, in this case, and this is corroborated by the remark that 
"If a method fn is not provided for a class method, the _superclass_ methd will 
be called" (my emphasis, note the docs' misspelling of 'methd').  However, the 
null result of (ancestors m) suggests instead that 'm' extends only Object, and 
that it handles _all_ of its method calling by delegation through reflection on 
the class being proxied.

It's the second interpretation that seems to explain why I can't override 
protected method 'finalize' (although that would suggest that I could create a 
new method 'finalize', which shadows Object.finalize without overriding it, and 
doesn't really explain why I'm seeing this error).  That said, however, the 
docs stress that "Note that while method fns can be provided to override 
protected methods...", which seems to say that what I'm trying to do, here, 
should be possible.  The rest of that sentence seems to suggest that something 
more complicated is happening, without revealing quite what.

Also Fogus and Houser (in The Joy of Clojure, p211) give an example of using 
'proxy', in which they illustrate a function proxying FilterOutputStream, and 
say that "The proxy returned by screaming-filter extends the Java class 
java.io.FilterOutputStream".  That seems to suggest that the proxy is indeed a 
subclass of the thing it's proxying.

Finally, the on-line discussion of gen-class at 
<http://clojure.org/compilation> mentions that one of the facilities it 
provides is "Exposing inherited protected members".  However the description of 
gen-class, there, does strongly suggest that it's a heavyweight, exotic thing, 
intended for fuller JVM interop rather than everyday use, and is telling me, in 
effect, "these aren't the macros you're looking for; move along".  It sounds as 
if getting involved in gen-class in this context would be an unidiomatic way of 
doing something fairly simple, namely producing an anonymous extension of a 
class which overrides a protected method.

What am I missing?

Thanks for any pointers.  Best wishes,

Norman


-- 
Norman Gray  :  http://nxg.me.uk



-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to