2009/8/14 Matthew Adams
<matthew@xxxxxxxxxxxxxxx>
OK, put your thinking caps on for this one. I'm getting introductions
on a type that doesn't match the declare parents type _expression_.
Consider the following Java artifacts, all defined in a package called
"example":
public class Foo() {}
public class Bar() {}
public interface HasFoo { Foo getFoo(); }
public interface HasBar extends HasFoo { Bar getBar(); }
public @interface Fooable {} // assume target is TYPE and retention RUNTIME
public @interface Barable {} // assume target is TYPE and retention RUNTIME
@Fooable public class MyFooable {}
@Barable public class MyBarable {}
Now, consider that I want to introduce an implementation of HasFoo to
classes annotated with @Fooable:
public aspect HasFooIntro {
declare parents: (@Fooable *) implements HasFoo;
private boolean HasFoo.returnNull = false;
public Foo HasFoo.getFoo() {
Foo foo = returnNull ? null : new Foo();
returnNull = !returnNull;
return foo;
}
}
...and HasBar to classes annotated with @Barable:
public aspect HasBarIntro {
declare parents: (@Barable *) implements HasBar;
public Bar HasBar.getBar() {
return getFoo() == null ? new Bar() : null;
}
}
When the compiler completes processing, I end up with expected results
when I call "javap example.MyFooable":
Compiled from "MyFooable.java"
public class example.MyFooable
extends java.lang.Object
implements example.HasFoo
{
public boolean ajc$interField$example_HasFooIntro$example_HasFoo$returnNull;
public example.MyFooable();
public boolean
ajc$interFieldGet$example_HasFooIntro$example_HasFoo$returnNull();
public void
ajc$interFieldSet$example_HasFooIntro$example_HasFoo$returnNull(boolean);
public example.Foo getFoo();
}
However, when I call "javap example.MyBarable", I get unexpected
results. Even though the type _expression_ in HasFooIntro's "declare
parents" doesn't match MyBarable, the introduced methods and fields of
HasFooIntro are present in MyBarable:
Question: How did the ITDs in HasFooIntro make it into MyBarable?
I'm confused because the declare parents type _expression_ of
HasFooIntro didn't match MyBarable, yet the HasFooIntro's
introductions are present in MyBarable.
Once
declare parents: (@Barable *) implements HasBar;
causes MyBarable to implement HasBar, the hierarchy for MyBarable includes HasFoo - so:
declare parents: (@Fooable *) implements HasFoo;
doesn't match because HasFoo is already there (since HasBar extends HasFoo). Same as
aspect X {
declare parents: C implements java.io.Serializable
}
class C implements java.io.Serializable {
}
doesn't show anything happening
ITD fields/methods on interfaces are put into the 'top most implementor' of the interface that is visible. In the HasFoo>HasBar>MyBarable case then MyBarable is the top most implementor where they can be added.
Your output was:
fooable.getFoo():example.Foo@
de6ced class example.Foo
fooable.getFoo():null (no class)
barable.getFoo():example.Foo@1fb8ee3 class example.Foo
barable.getFoo():null (no class)
barable.getBar():null (no class)
gooable.getFoo():example.Goo@10b30a7 class example.Goo
gooable.getFoo():example.Goo@1a758cb class example.Goo
gooable.getBar():null (no class)
would be useful to know what you were expecting to see?
As far as I can see
fooable.getFoo():example.Foo@de6ced class example.Foo // as expected because the returnNull flag is false, the flag is flipped
fooable.getFoo():null (no class) // as expected because the returnNull flag is true, the flag is flipped
barable.getFoo():example.Foo@1fb8ee3 class example.Foo // as expected because the returnNull flag is false
barable.getFoo():null (no class) // as expected because the returnNull flag is true, the flag is flipped
barable.getBar():null (no class) // as expected because getFoo() called underneath will return non-null, so getBar() returns null
gooable.getFoo():example.Goo@10b30a7 class example.Goo // as expected because Gooable.getFoo() returns new Goo
gooable.getFoo():example.Goo@1a758cb class example.Goo // as expected because Gooable.getFoo() returns new Goo
gooable.getBar():null (no class) // as expected because getFoo() returns an instance, so getBar() returns null
what did you want it to do?
cheers,
Andy
Now, let's say that I want to allow the author of a class annotated
with @Barable to provide its own getFoo() method (required by HasFoo,
the superinterface of HasBar) with a new implementation that returns a
Goo:
public class Goo extends Foo {}
@Barable
public class MyGooable {
public Foo getFoo() {
return new Goo();
}
}
Given this new class, when I call "javap example.MyGooable", I get the
following results:
When I run the following class, I get the results shown below.
public class Main {
public static void main(String[] args) {
Foo foo = null;
Bar bar = null;
MyFooable fooable = new MyFooable();
foo = fooable.getFoo();
System.out.println("fooable.getFoo():" + foo + " "
+ (foo == null ? "(no class)" : foo.getClass()));
foo = fooable.getFoo();
System.out.println("fooable.getFoo():" + foo + " "
+ (foo == null ? "(no class)" : foo.getClass()));
MyBarable barable = new MyBarable();
foo = barable.getFoo();
System.out.println("barable.getFoo():" + foo + " "
+ (foo == null ? "(no class)" : foo.getClass()));
foo = barable.getFoo();
System.out.println("barable.getFoo():" + foo + " "
+ (foo == null ? "(no class)" : foo.getClass()));
bar = barable.getBar();
System.out.println("barable.getBar():" + bar + " "
+ (bar == null ? "(no class)" : bar.getClass()));
MyGooable gooable = new MyGooable();
foo = gooable.getFoo();
System.out.println("gooable.getFoo():" + foo + " "
+ (foo == null ? "(no class)" : foo.getClass()));
foo = gooable.getFoo();
System.out.println("gooable.getFoo():" + foo + " "
+ (foo == null ? "(no class)" : foo.getClass()));
bar = gooable.getBar();
System.out.println("gooable.getBar():" + bar + " "
+ (bar == null ? "(no class)" :
bar.getClass()));
}
}
Results:
fooable.getFoo():example.Foo@de6ced class example.Foo
fooable.getFoo():null (no class)
barable.getFoo():example.Foo@1fb8ee3 class example.Foo
barable.getFoo():null (no class)
barable.getBar():null (no class)
gooable.getFoo():example.Goo@10b30a7 class example.Goo
gooable.getFoo():example.Goo@1a758cb class example.Goo
gooable.getBar():null (no class)
Thanks for your help, especially if you read this far! :) I'd be
happy to zip up the example and send it if you're interested.
-matthew
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users