Re: abstract static methods (again)
On Tue, 20 Oct 2009 14:07:22 +0000, Andreas Leitgeb wrote:
Tomas Mikula <tomas.mikula@gmail.com> wrote:
The idea here was to automate the reflection.
Sorry, that is a non-starter.
If you don't know the class at compiletime, then neither does the
compiler, so there's nothing the compiler could possibly do for you
beyond what it already does, namely write bytecode to have the JVM
check it all at runtime.
In my original post I noted that the use of Class's newly introduced
method
<T> Implementation<T> asImplementationOf(Class<T> clazz);
would have the restriction that the type T is known at compile time.
The syntax you use suggests, that the result of that function would be
some object (yes, an instance, a bit like the Class-Objects), that
offers methods to call the dynamically loaded class' static methods...
class MyBase {
static abstract void foo();
}
class MyImpl extends MyBase {
static void foo() { System.out.println("Called me"); }
}
use:
Implementation<MyBase> impl = Class.forName("MyImpl").
asImplementationOf(MyBase.class);
impl.foo(); // prints "Called me".
Implementation<MyBase> implFail = Class.forName("MyBase").
asImplementationOf(MyBase.class);
// the preceding line throws error, because MyBase doesn't //
*implement* the abstract method foo().
Is that your intention?
Yes.
If yes, please read on; If no, the rest of my posting may be moot.
In this case, the compiler can generate the bytecode to check if the
'this' class implements T.
I think, that whenever such a hierarchy of static methods is wanted, an
alternative solution with virtual (i.e. non-static) methods is easily
available with (if at all) only small cosmetic "up to taste" drawbacks.
- it requires to get an unnecessary instance (not so bad yet); -
getting this instance requires reflection
Reflection already starts at Class.forName(...) and if I understood
correctly, you didn't intend to replace that call.
Correct.
- using reflection for getting an instance requires conventions
which cannot be checked at runtime (such as the presence of some
particular (e.g. no-arg) constructor)
Of course it *can* be checked *at runtime*!
Sorry, I meant compile time. But they still can't be checked _elegantly_
at runtime.
See Class.newInstance().
If that throws an Exception, then there obviously was some problem in
the attempt to call the no-args constructor of the class. This simple
line:
MyBase mb = (MyBase)Class.forName("MyImpl").newInstance();
already checks *at runtime*, that
- the named class is loadable
- the named class has a no-args c'tor - the no-args c'tor succeeded
(did not throw an exception itself) - the thusly construed instance is
castable to "MyBase".
I was aware of this simple and only example where the convention can be
checked at runtime quite concisely. What if I want to use another
constructor and, say, two static methods. Things get a little messy.
Furthermore, if I forget to override pseudoStatic() or realStatic() in
a subclass, I will get the realStatic() from superclass, which is not
what I want.
If you forgot to override pseudoStatic(), then the derived class will
not even compile (assuming it is not declared as abstract, itself). For
non-static methods, all those mechanisms are already well worked out.
It will compile. Consider
abstract class A {
public abstract void pseudoStatic();
}
class B extends A {
public static void realStatic(){...}
public void pseudoStatic(){ realStatic(); }
}
class C extends B {
// If I forget to override pseudoStatic, I get the one from B.
// If I provide pseudoStatic, but not realStatic,
// I get realStatic from B.
}
So I really need to provide them both, but the compiler doesn't force me
to do so. I could make the realStatic private to reduce the danger to
half, but then I wouldn't be able to call it the classic way C.realStatic
().
Overriding realStatic() is not an issue, as you just wouldn't define it
in the base class, and so the call to realStatic() in the overridden
pseudoStatic() would fail at compile time, until you either add a
realStatic() method, or just did something else in the (enforcedly
existing) implementation of pseudoStatic().
The same applies here.
??I don't think, that calling static methods on dynamically
named classes is worth such deep changes as you seem to have in mind
for this task.
The good thing about it is that the changes are not real changes, just
extensions. So far I think they are all backward compatible with
current specification. No old code would be broken if these extensions
are introduced.
I do not even doubt that.
It's just that these extensions add much too much fuss and doesn't seem
to gain a substantial advantage in return.
Okay, thank you for the opinion. I still find the concept of enforced
static methods/constructors and the ability to call them on generic type
parameters very useful. But I may be biased towards my recent needs. I
would of course not insist on the syntax/API proposed here. It was just
the first idea that seemed quite consistent.