groovy - Simulating duck typing in Java -


the problem: i'd able generically access in java property/field on java ojbect how dynamic language (think groovy, javascript) would. won't know @ time i'm writing plumbing code type of object or property/field name be. know property/field name when go use it.

my current solution: far i've written simple wrapper class uses java.beans.introspector grab properties of bean/pojo , expose them map<string, object>. it's crude works simple cases.

my question other methodologies there approaching problem besides reflection / converting map?

before go further down path, i'd know if knows how cannibalize out of rhino or perhaps javax.script.* has thought out implementation of concept. or perhaps entirely different approach haven't considered.

edit: yes i'm familiar reflection (which believe introspector using under hood anyway). curious if there other thought out solutions.

edit 2: appears popular answers involve 1) reflection either directly or via helper classes, and/or 2) mapping interfaces implement desired class members. i'm intrigued comment talks leveraging groovy. since groovy has true duck-typing , jvm language, there way make simple helper in groovy , call java? cool , more flexible , perform better.

answer: marked mike's answer best since complete concept comes closest. won't go route particular case, useful approach. looking through should sure read conversations on here there lot of useful info in there well.

thanks!

if know set of apis want expose, know want access length method , iterator method, can define interface:

public interface theinterfaceiwant {   int length();   void quack(); } 

and want able use interface access corresponding methods on instances not implement interface, can use proxy classes : http://download.oracle.com/javase/1.4.2/docs/api/java/lang/reflect/proxy.html

so create proxy

final object aduck = ...; theinterfaceiwant aduckwrapper = (theinterfaceiwant) proxy.newproxyinstance(     theinterfaceiwant.class.getclassloader(),     new class[] { theinterfaceiwant.class },     new invocationhandler() {       public object invoke(           object proxy, method method, object[] args)           throws throwable {         return aduck.getclass().getmethod(             method.getname(), method.getparametertypes()).invoke(aduck, args);       }     }); 

then can use wrapper duck in dynamically typed language.

if (aduckwrapper.length() > 0) {   aduckwrapper.quack(); } 

here's full length runnable example prints "quack" 4 times using wrapper:

import java.lang.reflect.*;  public class duck {    // interface use access duck typed object.   public interface theinterfaceiwant {     int length();     void quack();   }    // underlying instance not implement theinterfaceiwant!   static final class foo {     public int length() { return 4; }     public void quack() { system.out.println("quack"); }   }    public static void main(string[] args) throws exception {     // create instance cast away useful type info.     final object aduck = new foo();      theinterfaceiwant aduckwrapper = (theinterfaceiwant) proxy.newproxyinstance(         theinterfaceiwant.class.getclassloader(),         new class[] { theinterfaceiwant.class },         new invocationhandler() {           public object invoke(               object proxy, method method, object[] args)               throws throwable {             return aduck.getclass().getmethod(                 method.getname(), method.getparametertypes()).invoke(aduck, args);           }         });      (int n = aduckwrapper.length(); --n >= 0;) {       // calling aduck.quack() here invalid since object.       aduckwrapper.quack();     }   } } 

Comments

Popular posts from this blog

asp.net - repeatedly call AddImageUrl(url) to assemble pdf document -

java - Android recognize cell phone with keyboard or not? -

iphone - How would you achieve a LED Scrolling effect? -