abstract static methods (again)

A

Andreas Leitgeb

Tom Anderson said:
This problem was solved in the golden age of the Patternists. The solution
is that you don't load Entertainers, you load EntertainerAgencies.

Oh, nice! Yet another extra indirection!
Wasn't there some "computer law" that said, that any problem can be
addressed (but not necessarily solved) by adding another level of
indirection?
public interface EntertainerAgency {
public Entertainer hire();
}

In that case, I'd *demand* EntertainerAgencies to offer a no-args c'tor,
until Eric comes up with ComedianAgency that just wants a default joke
for the Comedians it has under contract itself.
The question of some putative Entertainer constructor goes away. You do
have the question of the EntertainerAgency constructor, but this is much
less pressing. If it really worries you, use a EntertainerAgencyFactory.

And then an EntertainerAgencyMetaFactory for that, just in case...
Before you ask, yes, it's factories all the way down. Until you reach the
turtles.

What? They don't yet have a TurtleFactory?
Someone instantly go complain to T.P.!
 
A

Arved Sandstrom

Andreas Leitgeb wrote:
[ SNIP ]
This whole topic is inspired by dynamic loading of classes. Otherwise, there
wouldn't really be any use for dictating constructors at all. Dynamic loading
of classes seems to me of increasing importance with all those AppServers,
J2EE, ... Demanding the default-constructor (or even with a specific set
of arguments) for those classes imposes no new restriction, just formalizes
the restrictions that were already imposed by documentation and use.

PS: In recent threads I spoke up against restrictions, and now I promote them?
It's different types of restrictions, of course: an extra method or c'tor
is easily added as a dummy, but an idly added "final" is much harder to come
by, if deemed improper, later.

This is a major use-case, yes. JPA EJB3 entities and JSF managed beans,
to take 2 examples, are user-defined classes that require no-args ctors.
It's not that common to explicitly construct JSF managed beans, so no
real issue there, but I already mentioned the usefulness of enforcing
the presence of no-args ctors for JPA entities.

I don't see this exact use-case as being _highly_ compelling, but an
argument can be made that a mechanism for enforcing no-args ctors where
they are required is nonetheless mildly useful in the context of dotting
all the i's and crossing all the t's.

I agree with you that the annotations approach (which works quite well
for any kind of ctor, not just the no-args one) would be nicer if common
annotations were a bit more "standardized." Java 6 has been out for a
while and so I'm surprised (a bit) that this evidently hasn't happened
(like an Apache Commons Annotations project or something, although there
are 3rd party libraries that supply various sets of useful or
semi-useful compile-time annotations.) And there're still plenty of
misconceptions out there; I ran across this quote:

"Unless you are writing your own Java compiler, it is not possible to
create your own useful compile-time annotations."

in one article. This perception is obviously preventing some people from
writing or even looking for annotations of a certain sort.

If useful annotations were to be truly standardized then I guess they'd
end up in JSR-250, and therefore probably in javax.annotation.*.

AHS
 
A

Andreas Leitgeb

Arved Sandstrom said:
This is a major use-case, yes. JPA EJB3 entities and JSF managed beans,
to take 2 examples, are user-defined classes that require no-args ctors.
It's not that common to explicitly construct JSF managed beans, so no
real issue there, but I already mentioned the usefulness of enforcing
the presence of no-args ctors for JPA entities. Yes.

I don't see this exact use-case as being _highly_ compelling, but an
argument can be made that a mechanism for enforcing no-args ctors where
they are required is nonetheless mildly useful in the context of dotting
all the i's and crossing all the t's.

I'm not familiar with that idiom, but an uncrossed "t" is hardly a "t",
but rather an "l" (well, depending on the font, perhaps). With that,
the question of enforcing c'tors is even less "compelling" than making a
"t" a real "t".

It's not about achieving new possibilities, but only about shifting the
diagnosis of some programming error from runtime to compiletime - namely
to the time of compiling certain derived classes whose primary use is
eventually being Class.forName(...).getInstance(...)'ed.
I agree with you that the annotations approach (which works quite well
for any kind of ctor, not just the no-args one) would be nicer if common
annotations were a bit more "standardized." ...

Amen :) If those annotations were already standard, the discussion
about other (new) mechanisms to enforce c'tors would be moot.
 
A

Andreas Leitgeb

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?
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.
- 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*! 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".
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.

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 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.
 
A

Andreas Leitgeb

(this is a supercede to correct my mistake: getInstance -> newInstance )

Arved Sandstrom said:
This is a major use-case, yes. JPA EJB3 entities and JSF managed beans,
to take 2 examples, are user-defined classes that require no-args ctors.
It's not that common to explicitly construct JSF managed beans, so no
real issue there, but I already mentioned the usefulness of enforcing
the presence of no-args ctors for JPA entities. Yes.

I don't see this exact use-case as being _highly_ compelling, but an
argument can be made that a mechanism for enforcing no-args ctors where
they are required is nonetheless mildly useful in the context of dotting
all the i's and crossing all the t's.

I'm not familiar with that idiom, but an uncrossed "t" is hardly a "t",
but rather an "l" (well, depending on the font, perhaps). With that,
the question of enforcing c'tors is even less "compelling" than making a
"t" a real "t".

It's not about achieving new possibilities, but only about shifting the
diagnosis of some programming error from runtime to compiletime - namely
to the time of compiling certain derived classes whose primary use is
eventually being Class.forName(...).newInstance(...)'ed.
I agree with you that the annotations approach (which works quite well
for any kind of ctor, not just the no-args one) would be nicer if common
annotations were a bit more "standardized." ...

Amen :) If those annotations were already standard, the discussion
about other (new) mechanisms to enforce c'tors would be moot.
 
D

Daniel Pitts

Tomas said:
Tomas said:
On Sun, 18 Oct 2009 19:19:55 -0700, Peter Duniho wrote:

Tomas Mikula wrote:
I have searched this group for "abstract static methods" and found a
couple of threads, but I think none of them was discussing the kind
of semantics I am going to describe. As you might have guessed, I
believe it would be useful :). [...]
You aren't the first. However, in C++, C#, Java, and languages like
them, you simply are never going to have methods that are both virtual
and static. And since abstract implies virtual, that rules out
abstract static methods too.
I'm not talking about virtual static methods. In this case, abstract
would not imply virtual. My second use case could most probably be
accomplished in C++ by Concepts (though Concepts didn't make it to C+
+0x). In fact, it is achievable with current C++ templates, only
without compile time checking --- it is possible to call
T::staticMethod() where T is a template parameter.
C++ Template programming provides compile-time polymorphism. In Java,
you don't have Templates, so there is no similar approach.

If you think you need a "static" method to be overidden, then you really
need to have a non-static method, on a polymorphic object.

I rather think that sometimes I need to enforce that the static method
_will_ be overridden in every subclass. Non-static methods do not enforce
overriding, because they inherit the implementation from superclass. Note
that I don't want that the following example outputs "B", as was proposed
in some other discussions about abstract static methods.

class A {
static void f(){ System.out.println("A"); }
}

class B extends A {
static void f(){ System.out.println("B"); }
}

A a = new B();
a.f();

Why do you want to enforce a static method to exist in children? I can
think of no good reason for it.
 
T

Tomas Mikula

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.


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.

Reflection already starts at Class.forName(...) and if I understood
correctly, you didn't intend to replace that call.
Correct.


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.
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 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.
 
T

Tomas Mikula

Why do you want to enforce a static method to exist in children? I can
think of no good reason for it.

And I also want to enforce constructors. I provided two use-cases.

1. serialization frameworks. It is already required that a Serializable
class has a no-arg constructor. But this is not required at compile time.
Other variant is to require some particular constructor or a creator
static method, such as MyClass.readObject(ObjectInputStream) (though this
method is non-static and not mandatory in Serializable).

2. For calling static methods on generics. My example was
abstract class Vector<V extends Vector<V>>{
/** returns a zero vector */
public abstract static V zero();
}

Then somewhere else I would like to use code as this:

MyClass<V implements Vector<V>> { // 'implements' is not valid here now
...
V v = V.zero(); // not possible now
...
}
 
T

Tomas Mikula

The current plan is to support 'static' on the implementation of whole
interfaces, rather than on individual methods. Given a class such as:

class X implements static Runnable {
public static void run() { ... }
}

...then you could write X.static, and get a normal Runnable on which you
could invoke run(), and it would actually invoke X.run().

Now if you had

class Y extends X {...}

would the compiler enforce that Y provides its own implementation of
static run() method? (My desirable answer would be YES.)

If you had an abstract class
abstract class X implements static Runnable {...},
would the implementation of static method run() still be required? (My
desirable answer would be NO.)
If X was
loaded dynamically, you could get the same Runnable:

Class<?> clazz = Class.forName("X");
if (clazz.meetsContract(Runnable.class)) {
Runnable r = clazz.contractOn(Runnable.class); ...
}

I like this. As opposed to my proposal, this does not require some
'magic' class.
So you can invoke a static method on the dynamically loaded class
without method reflection. And X can be checked at compile-time that it
provides required static methods.


It would work by the compiler generating an extra class when it saw
'implements static'.

Somehow I feel that for consistency any class should support X.static,
not just when it 'implements static' some interface. But I'm curious what
was the motivation for having X.static? I only see usability if it was
allowed to use it on type parameters:

class MyClass<T static implements Runnable> {
...
T.static.run();
...
}
For X, that would be:

class X$static implements Runnable {
public void run() {
X.run();
}
}

Each Class object would have a proxy object (created on demand), which
would be an instance of X$static in this case. By being loaded with the
same ClassLoader as X, the X.run() call would bind to the correct
X#run() static method.

An expression such as:

X.static

...would expand to:

(X$static) X.class.getContractor()

Class#getContractor() would create the proxy or recover a cached one.

Or maybe X.static could just expand to X._static where the line

public static final X$static _static = new X$static();

would be added to class X.
Maybe the OP could check whether his requirements would be met by such a
feature.

If we agreed on the answers to the 2 above questions, then this would met
one part of my requirements, namely enforcing own implementation of
static methods and ease of calling them on dynamically loaded classes. (I
also wanted to enforce constructors, but they could be replaced by static
creator methods.)

The part not met by your proposal is calling static methods (and
constructors) on type parameters. But this would be a big task and
probably the best thing is to wait for reified generics first.
 
D

Daniel Pitts

Eric said:
You've said this a couple times, but are you sure it's true?
This class (with no no-arg constructor) appears to serialize and
deserialize just fine:

Only the non-Serializable Base of a Serializable class requires a
no-args constructor:

To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.

During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.


Anyway, if you are developing frameworks, then you might just have to
settle for runtime validation of these constraints, or invent your own
language that enforces them.
 
D

Daniel Pitts

Eric said:
Daniel said:
Eric said:
Tomas Mikula wrote:
[...]
1. serialization frameworks. It is already required that a
Serializable class has a no-arg constructor. But this is not
required at compile time.

You've said this a couple times, but are you sure it's true?
This class (with no no-arg constructor) appears to serialize and
deserialize just fine:

Only the non-Serializable Base of a Serializable class requires a
no-args constructor: [...]

Right. Which means that if an interface could mandate a specific
constructor for its implementing classes, this capability would not
solve Serializable's problem at all: It's not the Serializable class
that needs the special constructor, but a superclass that *doesn't*
implement Serializable. If we get to the point where an interface
can impose requirements on the classes that *don't* implement it, I
think we've achieved absurdity ;-)

There may yet be a reasonable use case for letting an interface
or abstract class require specified constructor signatures of the
implementing subclasses, but Serializable isn't it. The others I've
seen mentioned in this thread don't seem compelling -- but, as I've
also said in this thread, my experience with such things is slight.
I'm still willing to be convinced; I'm just not convinced yet.
If the problem is "I want to know I can always pass these values in to
create an object", then your solution shouldn't be "Use reflection and
enforce constructors", it should be "Use a parameterized factory".

Same goes for enforcing static method existance. You really should
separate that out into its own class:

public interface SpecialFactory<T extends SpecialObject> {
T createEmpty();
T createFromFoo(Foo foo);
}

Now, you have no reflective games to play, and your compiler will
enforce better behavior.

Reflection does have its place, but there are a lot of very useful
things you can do without it.
 
T

Tomas Mikula

Daniel said:
Eric said:
Tomas Mikula wrote:
[...]
1. serialization frameworks. It is already required that a
Serializable class has a no-arg constructor. But this is not required
at compile time.

You've said this a couple times, but are you sure it's true?
This class (with no no-arg constructor) appears to serialize and
deserialize just fine:

Only the non-Serializable Base of a Serializable class requires a
no-args constructor: [...]

Ah, I was wrong with this. But this only means that the Java's
serialization doesn't use _any_ constructor to create an object. Which
means that it uses some tricks not available to the programmer (correct
me if I am wrong). In your own serialization framework you would need to
create the object being deserialized, so you would care about the
constructors available on your class, not the superclass.
 
A

Arved Sandstrom

Eric said:
Daniel said:
Eric said:
Tomas Mikula wrote:
[...]
1. serialization frameworks. It is already required that a
Serializable class has a no-arg constructor. But this is not
required at compile time.

You've said this a couple times, but are you sure it's true?
This class (with no no-arg constructor) appears to serialize and
deserialize just fine:

Only the non-Serializable Base of a Serializable class requires a
no-args constructor: [...]

Right. Which means that if an interface could mandate a specific
constructor for its implementing classes, this capability would not
solve Serializable's problem at all: It's not the Serializable class
that needs the special constructor, but a superclass that *doesn't*
implement Serializable. If we get to the point where an interface
can impose requirements on the classes that *don't* implement it, I
think we've achieved absurdity ;-)

There may yet be a reasonable use case for letting an interface
or abstract class require specified constructor signatures of the
implementing subclasses, but Serializable isn't it.

Maybe it's just me, but if I want an abstract class to require specific
constructor signatures of its subclasses, I give that abstract base
class that constructor. :)

[ SNIP ]

AHS
 
L

Lew

Tomas said:
2. For calling static methods on generics. My example was
abstract class Vector<V extends Vector<V>>{
/** returns a zero vector */
public abstract static V zero();
}

This would be an extreme change to the semantics of Java generics, most likely
very infeasible as stated. Type parameters are resolved per instance, and do
not apply class-wide.

How is it even possible for a class to know what type to use for 'V', when
every instance of that class could have a different type replacement for it?
 
A

Andreas Leitgeb

Arved Sandstrom said:
Maybe it's just me, but if I want an abstract class to require specific
constructor signatures of its subclasses, I give that abstract base
class that constructor. :)

You may of course do that, but that doesn't put any
constructor *requirements* upon the subclasses.
 
T

Tomas Mikula

This would be an extreme change to the semantics of Java generics, most
likely very infeasible as stated. Type parameters are resolved per
instance, and do not apply class-wide.

How is it even possible for a class to know what type to use for 'V',
when every instance of that class could have a different type
replacement for it?

Whenever you have an instance myObj of class MyClass<V>, the instance
would know the type of V (it is not true now, but hopefully will be true
someday in the future). Now if you call a method on myObj that calls a
static method (or constructor) on V, the method lookup would be done with
aid of myObj. If static means resolved at compile time, then yes, this is
against the nature of static. I don't know how difficult it would be to
implement, I just suggested it is feasible (and IMO useful).

And for the sake of completeness, if you have a generic method
parametrized by T, then it takes some parameter whose instance will know
the actual type of T. So again you have an instance to help to resolve
the T's static method/constructor.
 
E

Eric Sosman

Tomas said:
Daniel said:
Eric Sosman wrote:
Tomas Mikula wrote:
[...]
1. serialization frameworks. It is already required that a
Serializable class has a no-arg constructor. But this is not required
at compile time.
You've said this a couple times, but are you sure it's true?
This class (with no no-arg constructor) appears to serialize and
deserialize just fine:
Only the non-Serializable Base of a Serializable class requires a
no-args constructor: [...]

Ah, I was wrong with this. But this only means that the Java's
serialization doesn't use _any_ constructor to create an object.

It uses the no-args constructor for any non-Serializable
superclass of the object being deserialized. Since Object is
not Serializable, it follows that deserialization always invokes
at least one no-args constructor.

But it doesn't invoke any constructor for the "direct"
object itself, no.
Which
means that it uses some tricks not available to the programmer (correct
me if I am wrong).

Right. Among other things, the JVM may invoke private
methods (readObject, for example) of the Serializable class.
You couldn't do that from outside the class, not even by
writing bytecode instead of Java.
In your own serialization framework you would need to
create the object being deserialized, so you would care about the
constructors available on your class, not the superclass.

If you want to implement your own scheme for pickling and
reconstituting objects, others have suggested factory methods
and/or auxiliary "builder" objects. That might improve the case
for abstract static methods, but I still don't see it as a
persuasive argument for abstract constructors. YMMV.
 
T

Tomas Mikula

My initial answer is 'no'. Y$static would contain:

public void run() {
Y.run();
}

...which would just bind to X#run() if Y didn't provide its own #run().

However, I guess the compiler could enforce it, though I'm not sure if
one would want that in all situations. In its favour, while Y instances
might inherit behaviour available in X instances due to 'Y extends X',
there's no reason for the static aspect of Y to inherit the static
aspect of X, e.g. it does not necessarily follow that Y$static extends
X$static, or that (X implements static Runnable && Y extends X => Y
implements static Runnable). Hmm...

I would say 'yes', if only since 'abstract' has never affected static
methods.

It's true that it is mixing of notions. I mean something like 'abstract
with respect to static'. Maybe requiring both kinds of abstract to always
appear simultaneously isn't the best idea. Maybe this kind of abstract
could instead be denoted as 'implements abstract static' :)
In fact, since you expect (from the previous question) that any Y which
extends X must provide its own static run(), I don't see a point in
requiring X to 'implements static Runnable' if it's only going to leave
the implementation to a base class.

The point would be to enforce the subclasses to 'implement static'
Runnable. Consider again an abstract class Vector with static method
zero(), which should return a zero vector. Vector alone doesn't need
(even can't reasonably) implement zero(), but it wants to enforce its
implementation in all concrete subclasses.
For instance methods, where Y extends X, it's clear that having an X
reference could mean invoking a Y object, i.e. you have a piece of code
which syntactically only refers to type X but semantically could invoke
Y:

abstract class X { public abstract void doSomething(); } class Y extends
X { ... }

X ref = ...;
ref.doSomething(); // this piece

At run-time, you might be dealing with Y, but statically you have only
X. When do you have an analogous case for static methods?

I don't want to have an analog for static methods. If X 'implements
abstract static' Runnable, I wouldn't want to be able to call X.run() or
X.static.run().
In the dynamic-loading use-case, Y would be explicitly identified by
name (and passed to Class#forName(String)). You then check dynamically
that Y 'implements static Runnable' with a call to
Class#meetsContract(Runnable.class). Anything you say about X is
irrelevant.
Agreed.

In the reified-generics case, you might have a class that requires a
type parameter that 'implements static Runnable':

class Banana<T extends static Runnable> {
{
T.run();
}
}

(Aside: I don't see a point in distinguishing between 'extends' and
'implements' on a type parameter, as only one relationship needs to be
expressed, i.e. Class#isAssignableFrom(Class), which is the same whether
you're dealing with interfaces or classes.)

By 'implements' I meant what you mean by 'extends static'. I just needed
to distinguish it from 'extends' without introducing new keyword.
Then you write 'new Banana<Y>', and the compiler checks that Y
'implements static Runnable', and still X is not involved.

Can you write an example where some code statically uses X and that it
'implements static Runnable', but could actually end up invoking
Y#run()?

I can't. This was not my intention. On the other hand my intention was
that even when you call Y#run() you cannot end up invoking X#run().
Yes. For classes without any 'implements static', the proxy object that
X.static ultimately evaluates to (and which Class#getContractor()
returns) can just be an instance of Object, as there are no interfaces
that it has to conform to.

My intuition was that X.static should allow to invoke any static method
of X, not just the ones that appear in some interface that X statically
implements:

class X implements static Runnable {
public static void run(){...}
public static void another(){...}
}

X.static.another().

Not that this would be of any use, it just would feel natural. But then
you would need to generate X$static class for every class that has a
static method.
If nothing else, just to ensure that there is a static, type-safe,
compile-time way to obtain the proxy object. If you happen to know X
statically, and that 'X implements static Z', and something accepted a
Z, you could write doSomething(X.static).

As you said, X.static is a comfortable way to call
(X$static) X.class.getContractor().
Though in every concrete use it could be replaced by
X.class.contractOn(SomeInterface.class).

X.static is nice and concise, but IMO omitting it (and Class.getContractor
()) avoids some problems (if you agree that X.static should support all
X's static methods) without using much usefulness.
As you noted before, this sort of thing seems to require reification,
though it's pretty similar to something in Stefan's last topical blog
entry, where he felt that something could be done without reification.

I will yet need to look at it.
Good idea, though I don't think '_static' is an especially reserved name
(is it?). 'static' would never clash with any real class member, and
we're past syntactic analysis by now, so it should be expressible in
bytecode.

Then X.static could just expand to X.static, or?
One problem might be that Class#getContractor() would have to
reflectively look-up a static field on X, instead of just calling
Class.forName("X$static").newInstance().

Was there any other useful use of Class#getContractor() other than with
resolving X.static? If it now was not necessary for that, getContractor
could be omitted completely.
Also, there was an objection to increased object count, so creating on
demand seemed worthwhile.

I admit.

So, to sum up, the intersection of our ideas seems to be adding method
<T> T contractOn(Class<T> clazz);
to class Class.

This could be implemented as follows:

<T> T contractOn(Class<T> clazz){
return clazz.cast(Class.forName(this.getName() +
"$static").newInstance());
}

But we diverge on the opinion for what classes X there should be class X
$static. You say that only for classes that explicitely state 'implements
static', I say that also for all their subclasses. Further, we diverge on
whether Y$static could end up invoking X's static methods.
 
L

Lew

Tomas Mikula said:
Whenever you have an instance myObj of class MyClass<V>, the instance
would know the type of V (it is not true now, but hopefully will be true
someday in the future). Now if you call a method on myObj that calls a
static method (or constructor) on V, the method lookup would be done with
aid of myObj. If static means resolved at compile time, then yes, this is
against the nature of static. I don't know how difficult it would be to
implement, I just suggested it is feasible (and IMO useful).

Isn't that a violation of the fundamental semantic of 'static' as
"class-wide, does not use an instance to resolve"?

(Yes, it is.)

This is not a compile-time vs. run-time matter, despite your attempt
at misdirection. The semantic of 'static' applies at run time and
compile time, both. It means "class level". You suggest using an
instance-level semantic to resolve the meaning of a 'static'
construct. That is too fundamental a change.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top