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

Reply via email to