Skip to main content

Cleaner access to static methods/Constructors of dymanically loaded classes

3 replies [Last post]
Joined: 2006-01-07

When we handle classes dynamically (plugins especially) the access to their static elements and constructors is pretty messy. This, I think, has been a strong factor in the way such classes are designed. Always use a no-arg constructor, for example, and generally not a static method in sight.

I've been musing on this for some time, and it seemed to me we could do with something like an interface, but which was a property of the class, not the instance, and which dictated a contract for public constructors and static methods in the same way an interface does for the instance methods. OTOH it didn't seem a big enough issue to justify a change in the language.

Well, recently I had a thought, and I've implemented it as a small class library. I'm interested to see whether people think this would be a useful facility to add.

The way it works is that you write an interface which I'm calling a class template interface. For each method in the interface there is required to be a corresponding public static method or constructor in the class you are accessing. The corresponding method or constructor must have an assignment compatible signature. Method in the template corresponding to constructors are annotated @Constructor, and their name are ignored for matching purposes.

From this template interface you build a class template object. Then you pass the actual Class to this template object, and it returns a proxy object, implementing the template interface, which passes calls to the Class.

So, we might for example create

<br />
public interface NumberTemplate {<br />
   @Constructor Number fromString(String v) throws NumberFormatException;</p>
<p>   Number valueOf(String v) throws NumberFormatException;<br />
}<br />
<p>ClassTemplate nt = ClassTemplate.getInstance(Number.class);</p>
<p>try {<br />
   NumberTemplate it = nt.create(Integer.class);<br />
   Number v1 = it.fromString("55");<br />
   Number v2 = it.valueOf("99");<br />
   }<br />
 catch(ClassTemplateException e) {<br />
    // if Integer doesn't fit our template<br />
  } catch(NumberFormatException e) {<br />
   }<br />

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Joined: 2006-01-07

ps. Obviously it would be helpful if compliance with such an template interface could be checked at compile time. This could be handled without needing a change in the language if an annotation in the class was used to indicate the template it was supposed to comply with.

Joined: 2004-07-04

Is this made to avoid reflecting the class? And does the class library you produced does the reflection for you? Or am I missing something here?

Joined: 2006-01-07

Basically yes. Using the reflection API, as it is, is rather messy. Every call you make, you have to deal with about 4 exceptions relating to how well the class fits the reflection you're attempting.

The library class is implemented using the reflection interface, but it does all the comformataty testing in one place, so that one you've created a template object, you just make the calls in a straightforward way, only dealing with the exceptions that the static methods and constructors themselves might throw.

When you create a dynamic object, it's almost always preferable to assign it to an interface which it's required to implement rather than use Method objects for the instance method calls. This does the same thing for the constructors and static calls.