2009/8/14 Matthew Adams <[email protected]>
> 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....@de6ced class example.Foo
fooable.getFoo():null (no class)
barable.getFoo():example....@1fb8ee3 class example.Foo
barable.getFoo():null (no class)
barable.getBar():null (no class)
gooable.getFoo():example....@10b30a7 class example.Goo
gooable.getFoo():example....@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....@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....@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....@10b30a7 class example.Goo // as expected
because Gooable.getFoo() returns new Goo
gooable.getFoo():example....@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....@de6ced class example.Foo
> fooable.getFoo():null (no class)
> barable.getFoo():example....@1fb8ee3 class example.Foo
> barable.getFoo():null (no class)
> barable.getBar():null (no class)
> gooable.getFoo():example....@10b30a7 class example.Goo
> gooable.getFoo():example....@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
> [email protected]
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users