declare parents and generic type parameters

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

declare parents and generic type parameters

Jaime Metcher
Hello List,

I've been ruminating about some the problems I've been having with ITD's, and I'm speculating that some of them at least are due to a more rigorous treatment of generics in the last couple of major versions.  More specifically, I don't think it's possible for declare parents to reproduce an inheritance hierachy involving generics with type parameters.

To illustrate, lets consider this class hierarchy.  We have a class and superclass:

public class SuperThing {}
public class BaseObject extends SuperThing {}

And then we have some classes to interact with them:

public abstract class SuperManager<T> {
public T getSuperInstance() {
return getInstance();
}
public abstract T getInstance();
}

public class Manager extends SuperManager<BaseObject> {
public BaseObject getInstance() {
return new BaseObject();
}
}

So then if we call:

new Manager().getSuperInstance();

We get back an instance of type BaseObject, as we'd expect.  The type parameter T turns into BaseObject all the way up the tree.

Now let's replace the top level of inheritance with ITD declare parents statements.  First we remove the explicit inheritance:

public class BaseObject {}
public abstract class Manager {...}

and then reintroduce the inheritance via this aspect:

public aspect ThingExtender {
declare parents: Manager extends SuperManager;
declare parents: BaseObject extends SuperThing;
}

Now, if we call:

new Manager().getSuperInstance();

We get back an instance of type Object.  This is entirely understandable - AspectJ works with the erasure of generic types, and the erasure of T is just Object.

I know I could do:

declare parents: Manager extends SuperManager<BaseObject>;

to fix this particular case.  But in my real project, both Manager and BaseObject have many subclasses themselves, so this solution just pushes the problem down to the next level.

So, it's pretty clear that declare parents can't faithfully reproduce normal inheritance for generic type parameters.  Which leaves me wondering:

1. Is it supposed to?
2. Is that even possible?
3. Did this sort of thing really work once upon a time (around about AspectJ 1.6) and then stop working, or am I just imagining it?

Thanks for listening
Jaime



_______________________________________________
aspectj-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-users
Reply | Threaded
Open this post in threaded view
|

Re: declare parents and generic type parameters

Andy Clement
Hey,


So, it's pretty clear that declare parents can't faithfully reproduce normal inheritance for generic type parameters.  Which leaves me wondering:

1. Is it supposed to?
2. Is that even possible?
3. Did this sort of thing really work once upon a time (around about AspectJ 1.6) and then stop working, or am I just imagining it?

To faithfully reproduce the inheritance with the declare parents statement, I think the declare parents statements needs to do the same thing as the original declaration in the source when you have explicit extends. So your:

declare parents: Manager extends SuperManager<BaseObject>;

is the right thing if your goal is to extract the inheritance into an aspect.  Changing that to just:

declare parents: Manager extends SuperManager

means exactly what it means if you had that declaration in the original non-aspect version. ie. the raw type of SuperManager is used as the superclass and T therefore becomes Object. Obviously the code will still do the same thing at runtime either way, i.e. the runtime type of the return value of getSuperInstance() will be a BaseObject. But you can’t write:

BaseObject bo = new Manager().getSuperInstance();

if your Manager does not extend SuperManager<BaseObject>

It is possible something funky used to work and it has been tightened up as fixes have gone in (that is, it never should have worked).

What you would seem to need is that the declare parents infers the type bound for SuperManager based on the differing return values for getInstance() but AspectJ has never done that.  You could use a generic aspect, perhaps:

abstract aspect ThingExtender<Z> {
  declare parents: Manager extends SuperManager<Z>;
  declare parents: BaseObject extends SuperThing;
}

aspect BaseObjectVariant extends ThingExtender<BaseObject> {}

But it isn’t clear to me that’ll meet all your requirements.

cheers,
Andy

On Feb 19, 2016, at 12:20 AM, Jaime Metcher <[hidden email]> wrote:

Hello List,

I've been ruminating about some the problems I've been having with ITD's, and I'm speculating that some of them at least are due to a more rigorous treatment of generics in the last couple of major versions.  More specifically, I don't think it's possible for declare parents to reproduce an inheritance hierachy involving generics with type parameters.

To illustrate, lets consider this class hierarchy.  We have a class and superclass:

public class SuperThing {}
public class BaseObject extends SuperThing {}

And then we have some classes to interact with them:

public abstract class SuperManager<T> {
public T getSuperInstance() {
return getInstance();
}
public abstract T getInstance();
}

public class Manager extends SuperManager<BaseObject> {
public BaseObject getInstance() {
return new BaseObject();
}
}

So then if we call:

new Manager().getSuperInstance();

We get back an instance of type BaseObject, as we'd expect.  The type parameter T turns into BaseObject all the way up the tree.

Now let's replace the top level of inheritance with ITD declare parents statements.  First we remove the explicit inheritance:

public class BaseObject {}
public abstract class Manager {...}

and then reintroduce the inheritance via this aspect:

public aspect ThingExtender {
declare parents: Manager extends SuperManager;
declare parents: BaseObject extends SuperThing;
}

Now, if we call:

new Manager().getSuperInstance();

We get back an instance of type Object.  This is entirely understandable - AspectJ works with the erasure of generic types, and the erasure of T is just Object.

I know I could do:

declare parents: Manager extends SuperManager<BaseObject>;

to fix this particular case.  But in my real project, both Manager and BaseObject have many subclasses themselves, so this solution just pushes the problem down to the next level.

So, it's pretty clear that declare parents can't faithfully reproduce normal inheritance for generic type parameters.  Which leaves me wondering:

1. Is it supposed to?
2. Is that even possible?
3. Did this sort of thing really work once upon a time (around about AspectJ 1.6) and then stop working, or am I just imagining it?

Thanks for listening
Jaime


_______________________________________________
aspectj-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-users


_______________________________________________
aspectj-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-users
Reply | Threaded
Open this post in threaded view
|

Re: declare parents and generic type parameters

Jaime Metcher


On Sat, Feb 20, 2016 at 2:48 AM, Andy Clement <[hidden email]> wrote:
Hey,

To faithfully reproduce the inheritance with the declare parents statement, I think the declare parents statements needs to do the same thing as the original declaration in the source when you have explicit extends.

I think this is the key point.  For arbritrary subclasses of BaseObject, the only correct declaration that works in all cases is:

class Manager<T> extends SuperManager<T>

and then:

class SubClassAManager extends Manager<SubClassA>
class SubClassBManager extends Manager<SubClassB>

etc.

But to translate that to an aspect, we'd need to able to write:

declare parents: Manager<T> extends SuperManager<T>

which is not possible.

It is possible something funky used to work and it has been tightened up as fixes have gone in (that is, it never should have worked).

That's the impression I get.  Even tighter casting rules would do it.  The project I had where this worked was from the era where generics were relatively new and even javac has changed a lot since then.  It was also hugely complex and highly dependent on libraries of that era, so totally not worth trying to revive it to see how it worked.
 

What you would seem to need is that the declare parents infers the type bound for SuperManager based on the differing return values for getInstance() but AspectJ has never done that.  You could use a generic aspect, perhaps:

abstract aspect ThingExtender<Z> {
  declare parents: Manager extends SuperManager<Z>;
  declare parents: BaseObject extends SuperThing;
}

aspect BaseObjectVariant extends ThingExtender<BaseObject> {}

That's not a bad idea.  It would mean saying:

aspect SubClassAVariant extends ThingExtender<SubClassA>{}
aspect SubClassBVariant extends ThingExtender<SubClassB>{}

etc. (one for each subclass)

But given my real Thing extender is more complex than this example that's still a net win over replicating the raw declare parents lines X times. 

The other possiblity is to forget extending the inheritance chain and simply  introduce all of SuperManager's fields and methods into Manager using field and method ITD's, and ditto for SuperThing into BaseObject.  I went for the inheritance approach because a discrete superclass reads more coherently than a gaggle of ITDs, but otherwise this meets my needs just as well.  Then, if I need a visible change in the class hierarchy a non-generic marker interface would do the trick.


Anyway, thanks for the interesting discussion.  I think I have a better handle on what's possible and what's not - much improved from the "sometimes, magic happens!" level of understanding I started out with a couple of years ago :)

Regards
Jaime


_______________________________________________
aspectj-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-users