From: Steven Simpson on
Tomas Mikula wrote:
> On Wed, 21 Oct 2009 06:10:02 +0100, Steven Simpson wrote:
>
>> (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.
>

Okay, I did wonder. :-)

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

It had occurred to me too, but without a pressing need (and so no clear
requirements to help specify it exactly), it seems to be 'future work'.

> Then X.static
(in the source code)
> could just expand to X.static
(in the compiler's internal structures, where 'static' is just a field
name, not a keyword)

(So, yes, that's what it would expand to in the case of a static field
itself called 'static'.)

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

Class#getConstructor() as it stands is responsible for ensuring that
only proxy object exists per Class object. So if 'X implements static
Y, static Z':

Class<?> clazz = Class.forName("X");
assert clazz.contractOn(Y.class) == clazz.contractOn(Z.class);
assert clazz.contractOn(Y.class) == X.static;

You suggested this implementation (for when not using the 'static'
field, I presume):
> <T> T contractOn(Class<T> clazz){
> return clazz.cast(Class.forName(this.getName() +
> "$static").newInstance());
> }
>
....which would create as many instances as asked for. You could still
fold the caching into it, but since X.static requires that functionality
when there is no 'static' field, it is factored out as
Class#getConstructor().

If you follow the 'static' field approach:

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

Class#contractOn(Class) becomes:

<T> T contractOn(Class<T> clazz) {
return clazz.cast(getField("static").get(null));
}

....which is a reflective access. You could cache it here too, but
surely the main point of using the static field called 'static' is not
to have to install a caching mechanism.

--
ss at comp dot lancs dot ac dot uk
From: Steven Simpson on
posting-account=pAbxHwoAAAADCfRr12ntKYVMSzbDntdj

Tomas Mikula wrote:
> On Wed, 21 Oct 2009 06:10:02 +0100, Steven Simpson wrote:
>
>> 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.

I anticipated shortly after posting that your Vector example might be
what you were getting at. Here's how I think it would go (assuming
reified generics). Your original declaration:

class MyClass<V extends Vector<V>> {
public void someMethod(){
V v = V.zero();
...
}
}

So, on some class whose full implementation you don't know about, you
expect a (V zero()) method - so define an interface type for that:

interface Zero<V> {
V zero();
}

Now express two constraints on the type provided to MyClass:

class MyClass<V extends Vector<V> & V extends static Zero<V>> {
public void someMethod(){
V v = V.zero();
...
}
}

Does that work for you?

If so, there's no need to put an 'abstract static' on Vector. It's only
MyClass that imposes the requirement. Other classes analogous to
MyClass might not need to call zero(), and could use extensions of
Vector that don't also 'implement static Zero' - such extensions could
not exist if Vector imposed the requirement on all its descendants.

--
ss at comp dot lancs dot ac dot uk
From: Tomas Mikula on
On Wed, 21 Oct 2009 18:05:33 +0100, Steven Simpson wrote:

> posting-account=pAbxHwoAAAADCfRr12ntKYVMSzbDntdj
>
> Tomas Mikula wrote:
>> On Wed, 21 Oct 2009 06:10:02 +0100, Steven Simpson wrote:
>>
>>> 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.
>
> I anticipated shortly after posting that your Vector example might be
> what you were getting at. Here's how I think it would go (assuming
> reified generics). Your original declaration:
>
> class MyClass<V extends Vector<V>> {
> public void someMethod(){
> V v = V.zero();
> ...
> }
> }
>
> So, on some class whose full implementation you don't know about, you
> expect a (V zero()) method - so define an interface type for that:
>
> interface Zero<V> {
> V zero();
> }
>
> Now express two constraints on the type provided to MyClass:
>
> class MyClass<V extends Vector<V> & V extends static Zero<V>> {
> public void someMethod(){
> V v = V.zero();
> ...
> }
> }
>
> Does that work for you?

Yes, that would work for me. But you need to add a new syntax, namely the
'&' in the generic parameters.
From: Steven Simpson on
Steven Simpson wrote:
> ...which would create as many instances as asked for. You could still
> fold the caching into it, but since X.static requires that functionality
> when there is no 'static' field, it is factored out as
> Class#getConstructor().
>
D'oh! getContractor()!!

--
ss at comp dot lancs dot ac dot uk
From: Andreas Leitgeb on
Tomas Mikula <tomas.mikula(a)gmail.com> wrote:
>> MyBase mb = (MyBase)Class.forName("MyImpl").newInstance();
> 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.

The task itself is messy, and reflection is the tool designed to handle
the mess :-) . Any other tool wouldn't be less messy, but they might
move the mess somewhere else - e.g. create wrapper-classes to do the
static calls.

About this "each class (of some hierarchy) must provide its own
implementation of certain static methods" thing:

This is obviously even stricter as abstract virtual methods, which, once
implemented are inherited by subclasses without them having to reimplement
again. Is it just the factory-pattern, that drove you to this idea, or
are there also other patterns that you think would benefit from enforced
static method implementations? Or is it perhaps just a first step before
requesting also special virtual methods that need to be overridden in
each subclass?