Re: Separate interface and implemenation problem..
Lew wrote:
Steven Simpson wrote:
// Not real code
class MyClass implements static Runnable {
public static void run() { ... }
}
But that doesn't make Java sense. Static methods don't implement or
override static methods of supertypes, nor can static methods delegate
their action to subtype static methods.
The code is supposed to imply that the Class object for MyClass
effectively implements Runnable. When you look at the class
reflectively like this, the static method 'sort of' becomes non-static,
as it operates in the context of its Class object. Consider if the
class is loaded independently by two class loaders - even if they are
identical, their static fields are distinct, and may have been linked to
different instances of statically referenced classes. To invoke a
'static' method in this case, you have to specify which instance of
Class to use:
Class c1 = Class.forName("SomeClass", true, loader1);
Class c2 = Class.forName("SomeClass", true, loader2);
c1.getMethod(...).invoke(null, arg1, arg2);
// not the same as
c2.getMethod(...).invoke(null, arg1, arg2);
The real question to ask is just what benefit one would expect from a
static method in an interface that isn't already available from static
methods in classes.
I originally saw the idea here (by Stefan Schulz):
<http://www.jroller.com/jadda/entry/meta_interfaces_for_contracting_classes>
....and contributed to some later discussions.
The main one (for me, at least) was where you instantiate a factory
class reflectively using its zero argument constructor, just so you can
call one method on the instance:
interface SomeFactory {
Object createSomething();
}
Class<?> factoryClazz = Class.forName(clazzName);
SomeFactory factory = (SomeFactory) factoryClazz.newInstance();
Object obj = factory.createSomething();
This would be replaced by something like:
Class<?> factoryClazz = Class.forName(clazzName);
SomeFactory factory = (SomeFactory) factoryClazz;
Object obj = factory.createSomething();
So you're not (overtly) creating an intermediate object just to call one
method on it to get the intended object; the Class object itself appears
to implement SomeFactory, whose sole method is implemented by a static
one on the represented class. The user of the factory (the third line,
in isolation) is unaware that it's calling a static method (effectively
by factoryClazz.getMethod("createSomething").invoke(null)).
It turns out, we'd have had a lot of trouble making the Class object
(appear to) implement the interface, particularly since Class already
implements some of its own, so we'd have to generate an extra object
internally anyway:
SomeFactory factory = factoryClazz.getStaticInterface(SomeFactory.class);
The returned object would just be a proxy calling the appropriate static
methods.
Anyway, having considered it for some time, it doesn't buy you a lot
over the original code - it may be slightly more convenient or feel
cleaner in some way, but you're not otherwise achieving more than
before. But since Mark brought it up, I wondered if there was any more
compelling case. Stefan had some other ideas, especially related to
generics (see later blog entries), though I wasn't convinced.
Nevertheless, it was interesting.
--
ss at comp dot lancs dot ac dot uk